socket通信

  socket是应用层与TCP/IP协议族通信的中间软件抽象层,是一组接口。工作原理如下:

  具体过程:服务器端先初始化socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

socket属性

1.创建套接字

  套接字的特性由三个属性确定:域(domain), 类型(type)和协议(protocol)。

int socket(int domain, int type, int protocol);

  domain:指定socket的类型,一般为AF_INET;

  type:是SOCK_STREAM 或SOCK_DGRAM,分别表示TCP连接和UDP连接;

  protocol :通常赋值"0"。

socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。

2.命名套接字

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;
//addrlen常被设置为sizeof(struct sockaddr)。

  返回值:0表示成功;-1表示遇到错误,并将errno置为相应的错误号。

  端口号 : 一般不要置为小于1024的值,因为1~1024是保留端口号 ,可使用大于1024中任何一个没有被占用的端口号。

  addr的赋值如下:实现自动获得本机IP地址和随机获取一个没有被占用的端口号。

my_addr.sin_port = ;                   /* 系统随机选择一个未被使用的端口号 */
my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */

3.套接字地址结构

   套接字地址由结构sockaddr_in来指定,在头文件 <netinet/in.h> 中定义。

   第一个结构

struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[]; /* 14 字节的协议地址 */
};
  sa_family:一般为AF_INET;
  sa_data :包含该socket的IP地址和端口号。
  
  第二种结构:
struct sockaddr_in {
   short int sin_ family; /* 地址族 */
   unsigned short int sin_port; /* 端口号 */
   struct in_addr sin_addr; /* IP地址 */
   unsigned char sin_zero[]; /* 填充0 以保持与struct sockaddr同样大小 */
};

  sin_family :通常被赋AF_INET;

  sin_port和 sin_addr :转换成为网络字节优先顺序 。

  sin_zero :用来将sockaddr_in结构填充到与struct sockaddr同样的长度,应该用bzero()或memset()函数将其置为零。

  指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换,如果一个函数所需参数类型是sockaddr时,可以在函数调用的时候将一个指向sockaddr_in的指针转换为指向sockaddr的指针;或者相反。

  IP地址结构 in_addr 被定义为:

struct in_addr{
unsigned long int s_addr;
};

4.创建队列

int listen(int sockfd, int backlog); 
//backlog指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()它们

  backlog:队列中等待服务的请求数目,系统缺省值为20,常用值是5。

  返回值:-1表示遇到错误,errno被置为相应的错误码。

5.阻塞接收

  当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器 accept()它 。

int accept(int sockfd, void *addr, int *addrlen); 
//addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求);
//addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量。

  返回值:-1表示错误,并且设置相应的errno值。

6.请求连接

  connect()函数用来与远端服务器建立一个TCP连接。

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); 
//sockfd是目的服务器的sockt描述符;serv_addr是包含目的机IP地址和端口号的指针。

  返回值:-1表示遇到错误,并且设置相应的errno值。

7.数据传输

  send()和recv()——数据传输

int send(int sockfd, const void *msg, int len, int flags); 
//sockfd是你想用来传输数据的socket描述符,msg是一个指向要发送数据的指针,Len是以字节为单位的数据的长度。flags一般情况下置为0。

  返回值:返回实际发送出的字节数。当send()返回值与len不匹配时,应该对这种情况进行处理。

int recv(int sockfd,void *buf,int len,unsigned int flags);
//sockfd是接受数据的socket描述符;buf 是存放接收数据的缓冲区;len是缓冲的长度。Flags也被置为0。

  返回值:返回实际上接收的字节数,或当出现错误时,返回-1并置相应的errno值。

socket使用

例一:server端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h> #define MAXLINE 4096 int main( int argc, char** argv )
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[];
int n; if( ( listenfd = socket( AF_INET, SOCK_STREAM, ) ) == - )
{
printf( "create socket error: %s(errno: %d)\n",strerror( errno ),errno );
exit( );
} memset( &servaddr, , sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( ); if( bind( listenfd, ( struct sockaddr* )&servaddr, sizeof( servaddr ) ) == - )
{
printf( "bind socket error: %s(errno: %d)\n",strerror( errno ),errno );
exit( );
} if( listen( listenfd, ) == - )
{
printf( "listen socket error: %s(errno: %d)\n",strerror( errno ),errno );
exit( );
} printf( "======waiting for client's request======\n" );
while( )
{
if( ( connfd = accept( listenfd, ( struct sockaddr* )NULL, NULL ) ) == - )
{
printf( "accept socket error: %s(errno: %d)",strerror( errno ),errno );
continue;
}
n = recv( connfd, buff, MAXLINE, );
buff[n] = '\0';
printf( "recv msg from client: %s\n", buff );
close( connfd );
} close( listenfd );
}

client端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h> #define MAXLINE 4096 int main( int argc, char** argv )
{
int sockfd, n;
char recvline[], sendline[];
struct sockaddr_in servaddr;
#if 0
if( argc != )
{
printf( "usage: ./client <ipaddress>\n" );
exit( );
}
#endif
if( ( sockfd = socket( AF_INET, SOCK_STREAM, ) ) < )
{
printf( "create socket error: %s(errno: %d)\n", strerror( errno ),errno );
exit( );
} memset( &servaddr, , sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr( "109.123.123.36" );
servaddr.sin_port = htons( ); #if 0
if( inet_pton( AF_INET, argv[], &servaddr.sin_addr ) <= )
{
printf( "inet_pton error for %s\n",argv[] );
exit( );
}
#endif if( connect( sockfd, ( struct sockaddr* )&servaddr, sizeof( servaddr ) ) < )
{
printf( "connect error: %s(errno: %d)\n",strerror( errno ),errno );
exit( );
} printf( "send msg to server: \n" );
fgets( sendline, , stdin );
if( send( sockfd, sendline, strlen( sendline ), ) < )
{
printf( "send msg error: %s(errno: %d)\n", strerror( errno ), errno );
exit( );
} close( sockfd );
exit( );
}

例二:server端:

//s_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
socklen_t clt_addr_len;
int listen_fd;
int com_fd;
int ret;
int i;
static char recv_buf[];
int len;
struct sockaddr_un clt_addr;
struct sockaddr_un srv_addr;
listen_fd=socket(PF_UNIX,SOCK_STREAM,);
if(listen_fd<)
{
perror("cannot create communication socket");
return ;
} //set server addr_param
srv_addr.sun_family=AF_UNIX;
strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-);
unlink(UNIX_DOMAIN);
//bind sockfd & addr
ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-)
{
perror("cannot bind server socket");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//listen sockfd
ret=listen(listen_fd,);
if(ret==-)
{
perror("cannot listen the client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//have connect request use accept
len=sizeof(clt_addr);
com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);
if(com_fd<)
{
perror("cannot accept client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}
//read and printf sent client info
printf("\n=====info=====\n");
for(i=;i<;i++)
{
memset(recv_buf,,);
int num=read(com_fd,recv_buf,sizeof(recv_buf));
printf("Message from client (%d)) :%s\n",num,recv_buf);
}
close(com_fd);
close(listen_fd);
unlink(UNIX_DOMAIN);
return ;
}

client端

//c_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
int connect_fd;
int ret;
char snd_buf[];
int i;
static struct sockaddr_un srv_addr;
//creat unix socket
connect_fd=socket(PF_UNIX,SOCK_STREAM,);
if(connect_fd<)
{
perror("cannot create communication socket");
return ;
}
srv_addr.sun_family=AF_UNIX;
strcpy(srv_addr.sun_path,UNIX_DOMAIN);
//connect server
ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
if(ret==-)
{
perror("cannot connect to the server");
close(connect_fd);
return ;
}
memset(snd_buf,,);
strcpy(snd_buf,"message from client");
//send info server
for(i=;i<;i++)
write(connect_fd,snd_buf,sizeof(snd_buf));
close(connect_fd);
return ;
}

网络通信 --> socket通信的更多相关文章

  1. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  2. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  3. Socket 通信(基础原理、实时聊天系统雏形)

    什么是 Socket? Socket 英文直译为"孔或插座",也称为套接字.用于描述 IP 地址和端口号,是一种进程间的通信机制.你可以理解为 IP 地址确定了网内的唯一计算机,而 ...

  4. .net平台下C#socket通信(上)

    在开始介绍socket前先补充补充基础知识,在此基础上理解网络通信才会顺理成章,当然有基础的可以跳过去了.都是废话,进入正题. TCP/IP:Transmission Control Protocol ...

  5. 网络编程:Http通信与Socket通信

    http://note.youdao.com/share/?id=f14d304548003f65e34255d3ddf9df31&type=note 网络编程:Http通信与Socket通信 ...

  6. Java基础知识强化之网络编程笔记02:Socket通信原理图解

    1. Socket (1)Socket套接字  网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字 (2)Socket原理机制:  • 通信两端都有Socket.  • 网 ...

  7. Python Socket通信原理

    [Python之旅]第五篇(一):Python Socket通信原理   python Socket 通信理论 socket例子 摘要:  只要和网络服务涉及的,就离不开Socket以及Socket编 ...

  8. C#socket通信1

    .net平台下C#socket通信(上) 完全是基础,新手可以随意看看,大牛可以关闭浏览页了,哈哈. 在开始介绍socket前先补充补充基础知识,在此基础上理解网络通信才会顺理成章,当然有基础的可以跳 ...

  9. IOS 基于TCP的socket通信详解(原创)

    最近在整理通信层相关知识,这篇文章是边整理边写的,有些地方可能不够准确,还请各位路过的大牛专家指出来.这次整理的socket通信是基于TCP的,实现方式是GCD形式,以下记录的都是些理论知识,方便自己 ...

随机推荐

  1. Android View绘制和显示原理简介

    现在越来越多的应用开始重视流畅度方面的测试,了解Android应用程序是如何在屏幕上显示的则是基础中的基础,就让我们一起看看小小屏幕中大大的学问.这也是我下篇文章--<Android应用流畅度测 ...

  2. 笔记+R︱Logistics建模简述(logit值、sigmoid函数)

    本笔记源于CDA-DSC课程,由常国珍老师主讲.该训练营第一期为风控主题,培训内容十分紧凑,非常好,推荐:CDA数据科学家训练营 ---------------------------------- ...

  3. R语言︱决策树族——随机森林算法

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:有一篇<有监督学习选择深度学习 ...

  4. freemarker中的left_pad和right_pad

    freemarker中的left_pad和right_pad 1.简易说明 (1)left_pad 距左边 (2)right_pad 距右边 (3)当仅仅只有一个参数时,插入的是空白:当有两个参数时, ...

  5. Linux显示一个二进制文件或可执行文件的完整路径

    Linux显示一个二进制文件或可执行文件的完整路径 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ which halt /sbin/halt

  6. Linux系统挂载NTFS文件系统

     今天尝试并成功的将一块500G的移动硬盘挂载到了RHEL5的系统上,甚感欣慰.想到也许以后自己或其他同学们会有类似经历,于是尽量细致的记录于此.     无论是一块安装了Windows/Linu ...

  7. 使用WebApiClient请求和管理Restful Api

    前言 本篇文章的内容是WebApiClient应用说明篇,如果你没有了解过WebApiClient,可以先阅读以下相关文章: WebApi client 的面向切面编程 我来给.Net设计一款Http ...

  8. [CF940F]Machine Learning

    codeforces 一句话题意 求区间数字出现次数的mex,带修改 sol 带修膜队不解释 带修膜队的排序! struct query{ int id,l,r,t; bool operator &l ...

  9. 【BZOJ1096】【ZJOI2007】仓库建设(斜率优化,动态规划)

    [BZOJ1096][ZJOI2007]仓库建设(斜率优化,动态规划) 题面 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原 ...

  10. [BZOJ1031] [JSOI2007] 字符加密Cipher (后缀数组)

    Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作 ...