在Linux上实现的一个简单的socket通信实例:
server.c
1 #include<stdio.h> 2 //下面两个头文件是使用socket必须引入的 3 #include<sys/types.h> 4 #include<sys/socket.h> 5 6 #include<stdlib.h> 7 #include<netinet/in.h> 8 #include<arpa/inet.h> 9 //启动服务器通信端口 10 int startup(int _port,const char* _ip) 11 { 12 //socket()函数打开一个网络通信窗口,成功则返回一个文件描述符,应用程序可以向读写文件一样用read/write在网络上转发数据。若调用出错则返回-1 13 //socket()函数的三个参数:协议类型, 套接字类型, 协议类型的常量或设置为0 14 //AF_INET(IPv4协议) SOCK_STREAM字节流套接字 15 int sock=socket(AF_INET,SOCK_STREAM,0); 16 if(sock<0) 17 { 18 perror("socket"); 19 exit(1); 20 } 21 22 struct sockaddr_in local;//网络编程中常用的数据结构 23 local.sin_family=AF_INET;//IPVC4地址族 24 local.sin_port=htons(_port);//将端口地址转换为网络二进制数字 25 local.sin_addr.s_addr=inet_addr(_ip);//将网络地址转换为网络二进制数字 26 27 socklen_t len=sizeof(local); 28 //绑定套接字:成功返回0, 失败返回-1 29 //功能:将sock和local绑定在一起,使得sock这个用于网络通讯的问价描述符监听local所描述的地址和端口 30 if(bind(sock,(struct sockaddr*)&local,len)<0) 31 { 32 perror("bind"); 33 exit(2); 34 } 35 //listen(int sockfd, int backlog)监听函数,sockfd为要监听的socket套接字,backlog为可以排队的最大连接数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。监听成功返回0, 失败返回-1 36 if(listen(sock,5)<0) 37 { 38 perror("listen"); 39 exit(3); 40 } 41 return sock; 42 } 43 int main(int argc,char* argv[]) 44 { 45 if(argc!=3) 46 { 47 printf("Usage: [local_ip] [local_port]",argv[0]); 48 return 3; 49 } 50 //启动服务器套接字listen_socket 51 int listen_socket=startup(atoi(argv[2]),argv[1]); 52 53 struct sockaddr_in remote; 54 socklen_t len=sizeof(struct sockaddr_in); 55 56 while(1) 57 { 58 //accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)函数,sockfd为服务器的socket套接字,addr为客户端协议地址,addrlen为协议地址的长度, 59 //如果accept成功,则返回一个由内核自动生成的全新套接字,代表与返回客户的TCP连接 60 int socket=accept(listen_socket,(struct sockaddr*)&remote,&len); 61 if(socket<0) 62 { 63 perror("accept"); 64 continue; 65 } 66 //inet_ntoa:将网络二进制数字转换为网络地址 67 //ntohs:将网络二进制数字转换为端口号 68 printf("client,ip:%s,port:%d ",inet_ntoa(remote.sin_addr) 69 ,ntohs(remote.sin_port)); 70 71 72 char buf[1024]; 73 while(1) 74 { 75 //调用网络I/O进行读写 76 ssize_t _s=read(socket,buf,sizeof(buf)-1); 77 if(_s>0) 78 { 79 buf[_s]=0; 80 printf("client# %s ",buf); 81 } 82 else 83 { 84 printf("client is quit! "); 85 break; 86 } 87 88 } 89 //关闭套接字 90 close(socket); 91 } 92 return 0; 93 }
client.c
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<sys/types.h> 4 #include<sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 8 9 static void usage(const char* proc) 10 { 11 printf("usage:%s [ip] [port] ",proc); 12 } 13 14 int main(int argc,char* argv[]) 15 { 16 if(argc!=3) 17 { 18 usage(argv[0]); 19 return 3; 20 } 21 22 int sock=socket(AF_INET,SOCK_STREAM,0); 23 if(sock<0) 24 { 25 perror("socket"); 26 exit(1); 27 } 28 29 struct sockaddr_in server; 30 server.sin_family=AF_INET; 31 server.sin_port=htons(atoi(argv[2])); 32 server.sin_addr.s_addr = inet_addr(argv[1]); 33 //connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);sockfd为要监听的socket套接字,addr参数为服务器的socket地址,addrlen为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。 34 if(connect(sock,(struct sockaddr*)&server,(socklen_t)sizeof(server))<0) 35 { 36 perror("connect"); 37 exit(2); 38 } 39 40 char buf[1024]; 41 42 while(1) 43 { 44 printf("send#"); 45 fflush(stdout); 46 ssize_t _s=read(0,buf,sizeof(buf)-1); 47 buf[_s-1]=0; 48 write(sock,buf,_s); 49 } 50 51 close(sock); 52 return 0; 53 54 }
结果展示: