一what socket套接字也是一种文件格式,和管道文件一样,它是一种伪文件,存在于内核的缓冲区中,大小不变,一直是0。套接字一定是成对出现的,有server套接字,就一定有client套接字,它是一种全双工通信方式,分别有读写缓冲区通信框图,也称为cs架构如下 cs架构(bs架构,browserserver)服务器server客户端client1.请求协议版本1.请求协议版本2.创建socket2.创建socket3.创建协议地址族3.获取服务器协议地址族ip地址网络端口通信协议4.绑定5.监听6.等待客户端连接4.连接服务器7.通信5.通信8.关闭socket6.关闭socket9.清理协议版本7.清理协议版本 1.1和套接字相关的几个地址结构体 structsockaddr用来描述ipv4地址协议1.2和地址转换相关的几个函数 ip地址转换函数inet_pton..1.24--------------网络字节序/**参数af,网络ip地址的版本,ipv4或ipv6*src..1.24*dst网络字节序*/intinet_pton(intaf,constchar*src,void*dst);inet_ntop网络字节序--------------点分十进制/**参数af,网络ip地址的版本,ipv4或ipv6*src网络字节序*dst..1.24*size字符串dst长度*/constchar*inet_ntop(intaf,constvoid*src,char*dst,socklen_tsize); 二why 为什么需要套接字呢?它的目的是实现进程间通信,既可以实现同一个linux内核(同一台设备)进程间通信;又可以实现不同的linux内核(不同设备)进程间通信,比如我们浏览网页的过程其实就是一个socket通信模型。三how 本地套接字用于实现本机进程间通信,有tcp和udp类似两种,我们以类似tcp方式举例。3.1server端的流程 1.创建socketintifd=socket(AF_LOCAL,sock_stream,0);//AF_UNIX也可以,AF_INET是指网络套接字2.绑定structsockaddr_unstructsockaddr_unserv;serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.socket");//server.socket此时还不存在的,它什么时候会存在呢bind(ifd,(structsockaddr*)serv,sizeof(serv));//绑定成功,server.socket这个文件就会被创建3.设置监听listen()4.等待接收连接请求structsockaddr_unclient;intlen=sizeof(client);intcfd=accept(ifd,client,len);5.通信send//发送数据recv//接收数据6.断开连接 代码如下 #include"stdio.h"#include"stdlib.h"#includeunistd.h#include"sys/types.h"#includesys/stat.h#include"string.h"#includearpa/inet.h#includesys/un.hintmain(intargc,char*argv[]){intlfd,ret,cfd;structsockaddr_unserv,client;socklen_tlen=sizeof(client);charbuf[]={0};intrecvlen;//创建socketlfd=socket(AF_LOCAL,SOCK_STREAM,0);if(lfd==-1){perror("socketerror");return-1;}//初始化server信息serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.sock");//绑定ret=bind(lfd,(structsockaddr*)serv,sizeof(serv));if(ret==-1){perror("binderror");return-1;}//设置监听,设置能够同时和服务端连接的客户端数量ret=listen(lfd,36);if(ret==-1){perror("listenerror");return-1;}//等待客户端连接cfd=accept(lfd,(structsockaddr*)client,len);if(cfd==-1){perror("accepterror");return-1;}printf("=====clientbindfile:%s\n",client.sun_path);while(1){recvlen=recv(cfd,buf,sizeof(buf),0);if(recvlen==-1){perror("recverror");return-1;}elseif(recvlen==0){printf("clientdisconnet...\n");close(cfd);break;}else{printf("recvbuf%s\n",buf);send(cfd,buf,recvlen,0);}}close(cfd);close(lfd);return0;} 3.2client端的流程 1.创建socketintfd=socket(AF_LOCAL,sock_stream,0);//AF_UNIX也可以,AF_INET是指网络套接字2.绑定套接字文件structsockaddr_unclient;client.sun_family=AF_LOCAL;strcpy(client.sun_path,"client.socket");//client.socket此时还不存在的,它什么时候会存在呢bind(ifd,(structsockaddr*)client,len);//绑定成功,server.socket这个文件就会被创建3.连接服务器structsockaddr_unserv;serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.socket");//server.socket此时还不存在的,它什么时候会存在呢connect(fd,serv,sizeof(serv))4.通信recvsend5.关闭close 代码如下 #include"stdio.h"#include"stdlib.h"#includeunistd.h#include"sys/types.h"#includesys/stat.h#include"string.h"#includearpa/inet.h#includesys/un.hintmain(intargc,char*argv[]){intlfd,ret;structsockaddr_unserv,client;socklen_tlen=sizeof(client);charbuf[]={0};intrecvlen;//创建socketlfd=socket(AF_LOCAL,SOCK_STREAM,0);if(lfd==-1){perror("socketerror");return-1;}//给客户端绑定一个套接字文件client.sun_family=AF_LOCAL;strcpy(client.sun_path,"client.sock");ret=bind(lfd,(structsockaddr*)client,sizeof(client));if(ret==-1){perror("binderror");return-1;}//初始化server信息serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.sock");//连接connect(lfd,(structsockaddr*)serv,sizeof(serv));while(1){fgets(buf,sizeof(buf),stdin);send(lfd,buf,strlen(buf)+1,0);recv(lfd,buf,sizeof(buf),0);printf("recvbuf%s\n",buf);}close(lfd);return0;} 四test 4.1编译运行 分别编译server.c和client.c,先运行./server,我们发现在当前目录下创建了一个serve.sock的套接字文件,文件类型是“s”,如下:然后运行./client,同样发现创建了一个套接字文件client.sock,然后在client输入信息,就会在server端接收到信息了。4.2bug 我们会遇到一个问题,当我们停止./server或者./client,在运行./server或者./client,会发现一个错误提示这是因为套接字文件已经存在,不能再bind了,我们需要修改源程序,在bind之前,加上unlink,就是说如果套接字文件存在,需要先删除套接字文件。server代码修改如下 #include"stdio.h"#include"stdlib.h"#includeunistd.h#include"sys/types.h"#includesys/stat.h#include"string.h"#includearpa/inet.h#includesys/un.hintmain(intargc,char*argv[]){intlfd,ret,cfd;structsockaddr_unserv,client;socklen_tlen=sizeof(client);charbuf[]={0};intrecvlen;//创建socketlfd=socket(AF_LOCAL,SOCK_STREAM,0);if(lfd==-1){perror("socketerror");return-1;}//如果套接字文件存在,存删除套接字文件unlink("server.sock");//初始化server信息serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.sock");//绑定ret=bind(lfd,(structsockaddr*)serv,sizeof(serv));if(ret==-1){perror("binderror");return-1;}//监听ret=listen(lfd,36);if(ret==-1){perror("listenerror");return-1;}//等待客户端连接cfd=accept(lfd,(structsockaddr*)client,len);if(cfd==-1){perror("accepterror");return-1;}printf("=====clientbindfile:%s\n",client.sun_path);while(1){recvlen=recv(cfd,buf,sizeof(buf),0);if(recvlen==-1){perror("recverror");return-1;}elseif(recvlen==0){printf("clientdisconnet...\n");close(cfd);break;}else{printf("recvbuf%s\n",buf);send(cfd,buf,recvlen,0);}}close(cfd);close(lfd);return0;} client代码如下: #include"stdio.h"#include"stdlib.h"#includeunistd.h#include"sys/types.h"#includesys/stat.h#include"string.h"#includearpa/inet.h#includesys/un.hintmain(intargc,char*argv[]){intlfd,ret;structsockaddr_unserv,client;socklen_tlen=sizeof(client);charbuf[]={0};intrecvlen;//创建socketlfd=socket(AF_LOCAL,SOCK_STREAM,0);if(lfd==-1){perror("socketerror");return-1;}//如果套接字文件存在,存删除套接字文件unlink("client.sock");//给客户端绑定一个套接字文件client.sun_family=AF_LOCAL;strcpy(client.sun_path,"client.sock");ret=bind(lfd,(structsockaddr*)client,sizeof(client));if(ret==-1){perror("binderror");return-1;}//初始化server信息serv.sun_family=AF_LOCAL;strcpy(serv.sun_path,"server.sock");//连接connect(lfd,(structsockaddr*)serv,sizeof(serv));while(1){fgets(buf,sizeof(buf),stdin);send(lfd,buf,strlen(buf)+1,0);recv(lfd,buf,sizeof(buf),0);printf("recvbuf%s\n",buf);}close(lfd);return0;} 北京治白癜风专科医院孩子得了白癜风
|