Linux 网络编程一步一步学(六)-客户/服务端通信
CLIENT
1 #include <stdio.h> 2 #include <string.h> 3 #include <errno.h> 4 #include <sys/socket.h> 5 #include <resolv.h> 6 #include <stdlib.h> 7 #include <netinet/in.h> 8 #include <arpa/inet.h> 9 #include <unistd.h> 10 #define MAXBUF 1024 11 int main(int argc, char **argv) - 12 { | 13 int sockfd, len; | 14 struct sockaddr_in dest; | 15 char buffer[MAXBUF + 1]; - 16 if (argc != 3) { 2 17 printf("参数格式错误!正确用法如下:\n\t\t%s IP 地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",argv[0], argv[0]); 2 18 exit(0); 2 19 } | 20 /* 创建一个 socket 用于 tcp 通信 */ - 21 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 2 22 perror("Socket"); 2 23 exit(errno); 2 24 } | 25 printf("socket created\n"); | 26 /* 初始化服务器端(对方)的地址和端口信息 */ | 27 bzero(&dest, sizeof(dest)); | 28 dest.sin_family = AF_INET; | 29 dest.sin_port = htons(atoi(argv[2])); - 30 if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) { 2 31 perror(argv[1]); 2 32 exit(errno); 2 33 } | 34 printf("address created\n"); | 35 /* 连接服务器 */ - 36 if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { 2 37 perror("Connect "); 2 38 exit(errno); 2 39 } | 40 printf("server connected\n"); | 41 /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */ | 42 bzero(buffer, MAXBUF + 1); | 43 /* 接收服务器来的消息 */ | 44 len = recv(sockfd, buffer, MAXBUF, 0); | 45 if(len > 0) printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len); | 46 else printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno)); | 47 bzero(buffer, MAXBUF + 1); | 48 strcpy(buffer, "这是客户端发给服务器端的消息\n"); | 49 /* 发消息给服务器 */ | 50 len = send(sockfd, buffer, strlen(buffer), 0); | 51 if(len < 0) printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer,errno, strerror(errno)); | 52 else printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len); | 53 /* 关闭连接 */ | 54 close(sockfd); | 55 return 0; | 56 } 57
SERVER
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <errno.h> 4 #include <string.h> 5 #include <sys/types.h> 6 #include <netinet/in.h> 7 #include <sys/socket.h> 8 #include <sys/wait.h> 9 #include <unistd.h> 10 #include <arpa/inet.h> 11 #define MAXBUF 1024 12 int main(int argc, char **argv) - 13 { | 14 int sockfd, new_fd; | 15 socklen_t len; | 16 struct sockaddr_in my_addr, their_addr; | 17 unsigned int myport, lisnum; | 18 char buf[MAXBUF + 1]; | 19 if (argv[1]) | 20 myport = atoi(argv[1]); | 21 else | 22 myport = 7838; | 23 if (argv[2]) | 24 lisnum = atoi(argv[2]); | 25 else | 26 lisnum = 2; - 27 if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 2 28 perror("socket"); 2 29 exit(1); 2 30 } | 31 else printf("socket created\n"); | 32 | 33 bzero(&my_addr, sizeof(my_addr)); | 34 my_addr.sin_family = PF_INET; | 35 my_addr.sin_port = htons(myport); | 36 if(argv[3]) | 37 my_addr.sin_addr.s_addr = inet_addr(argv[3]); | 38 else | 39 my_addr.sin_addr.s_addr = INADDR_ANY; | 40 if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) - 41 { 2 42 perror("bind"); 2 43 exit(1); 2 44 } | 45 else printf("binded\n"); - 46 if (listen(sockfd, lisnum) == -1) { 2 47 perror("listen"); 2 48 exit(1); 2 49 } | 50 else printf("begin listen\n"); - 51 while(1) { 2 52 len = sizeof(struct sockaddr); - 53 if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -1) { 3 54 perror("accept"); 3 55 exit(errno); 3 56 } 2 57 else 2 58 printf("server: got connection from %s, port %d, socket%d\n",inet_ntoa(their_addr.sin_addr), ntohs(their_ad2dr.sin_port), new_fd); 2 59 /* 开始处理每个新连接上的数据收发 */ 2 60 bzero(buf, MAXBUF + 1); 2 61 strcpy(buf, "这是在连接建立成功后向客户端发送的第一个消息\n只能向new_fd这个用accept函数新建立的socket发消息,不能向sockfd这个监听socket发送消息,监听socket不能用来接收或发送消息\n"); 2 62 /* 发消息给客户端 */ 2 63 len = send(new_fd, buf, strlen(buf), 0); - 64 if(len < 0) { 3 65 printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, 3 66 strerror(errno)); 3 67 } 2 68 else printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len); 2 69 bzero(buf, MAXBUF + 1); 2 70 /* 接收客户端的消息 */ 2 71 len = recv(new_fd, buf, MAXBUF, 0); 2 72 if(len > 0) printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len); 2 73 else printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno)); 2 74 /* 处理每个新连接上的数据收发结束 */ 2 75 } | 76 close(sockfd); | 77 return 0; | 78 } 79
函数解释:
accept():用来接受参数s 的socket 连线. 参数s 的socket 必需先经bind()、listen()函数处理过, 当有连线进来时accept()会返回一个新的socket 处理代码, 往后的数据传送与读取就是经由新的socket处理, 而原来参数s 的socket 能继续使用accept()来接受新的连线要求. 连线成功时, 参数addr 所指的结构会被系统填入远程主机的地址数据, 参数addrlen 为scokaddr 的结构长度. 关于机构sockaddr 的定义请参考bind().
int accept(int s, struct sockaddr * addr, int * addrlen);
函数说明:accept()用来接受参数s 的socket 连线. 参数s 的socket 必需先经bind()、listen()函数处理过, 当有连线进来时accept()会返回一个新的socket 处理代码, 往后的数据传送与读取就是经由新的socket处理, 而原来参数s 的socket 能继续使用accept()来接受新的连线要求. 连线成功时, 参数addr 所指的结构会被系统填入远程主机的地址数据, 参数addrlen 为scokaddr 的结构长度. 关于机构sockaddr 的定义请参考bind().