TCP网络编程流程如下:
实现功能:服务器端与客户端成功通讯后返回get!
服务器端程序
1 #include <netdb.h> 2 #include <sys/socket.h> 3 #include <unistd.h> 4 #include <string.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <memory.h> 8 #include <signal.h> 9 #include <arpa/inet.h> 10 11 int sockfd; 12 13 void sig_handler(int signo) 14 { 15 if(signo == SIGINT) 16 { 17 printf("server close "); 18 /*步骤6:关闭socket*/ 19 close(sockfd); 20 exit(1); 21 } 22 } 23 24 /*输出连接上来的客户端相关信息*/ 25 void out_addr(struct sockaddr_in *clientaddr) 26 { 27 //将端口从网络字节序转换成主机字节序 28 int port = ntohs(clientaddr->sin_port); 29 char ip[16]; 30 memset(ip, 0, sizeof(ip)); 31 //将ip地址从网络字节序转换成点分十进制 32 inet_ntop(AF_INET, 33 &clientaddr->sin_addr.s_addr, ip, sizeof(ip)); 34 printf("client:%s(%d) connected ", ip, port); 35 } 36 37 void do_server(int fd) 38 { 39 40 //返回get! 41 char t[20] = "get!"; 42 char *s = t; 43 size_t size = (strlen(s)+1)*sizeof(char); 44 t[size-1] = ' '; 45 //将服务器获得的系统时间写回到客户端 46 if(write(fd, s, size) != size) 47 { 48 perror("write error"); 49 } 50 51 } 52 53 int main(int argc, char *argv[]) 54 { 55 if(argc < 2) 56 { 57 printf("usage: %s #port ",argv[0]); 58 exit(1); 59 } 60 if(signal(SIGINT, sig_handler) == SIG_ERR) 61 { 62 perror("signal sigint error"); 63 exit(1); 64 } 65 66 /* 步骤1: 创建socket(套接字) 67 * AF_INET:IPV4 68 * SOCK_STREAM:TCP协议 69 **/ 70 sockfd = socket(AF_INET, SOCK_STREAM, 0); 71 if(sockfd < 0) 72 { 73 perror("socket error"); 74 exit(1); 75 } 76 /* 步骤2:调用bind函数将socket和地址 77 * (包括ip、port)进行绑定 78 */ 79 struct sockaddr_in serveraddr; 80 memset(&serveraddr, 0, sizeof(serveraddr)); 81 //往地址中填入ip、port、internet地址族类型 82 serveraddr.sin_family = AF_INET;//IPV4 83 serveraddr.sin_port = htons(atoi(argv[1])); 84 serveraddr.sin_addr.s_addr = INADDR_ANY; 85 //监听所有服务器上ip得到的连接请求 86 // #define INADDR_ANY (uint32_t)0x00000000 87 if(bind(sockfd,(struct sockaddr*)&serveraddr, 88 sizeof(serveraddr)) < 0) 89 { 90 perror("bind error"); 91 exit(1); 92 } 93 94 /* 95 * 步骤3:调用listen函数启动监听(指定port监听) 96 * 通知系统去接受来自客户端的连接请求 97 * (将接受到的客户端的连接请求放置到对应的队列中) 98 × 第二个参数:指定队列的长度 99 */ 100 if(listen(sockfd, 10) < 0) 101 { 102 perror("listen error"); 103 exit(1); 104 } 105 106 /* 107 * 步骤4:调用accept函数从队列中获得 108 * 一个客户端的请求连接,并返回新的 109 * 注意:若没有客户端连接,调用此函数后会阻塞, 110 * 直到获得一改客户端的链接。 111 */ 112 struct sockaddr_in clientaddr; 113 socklen_t clientaddr_len = sizeof(clientaddr); 114 while(1) 115 { 116 int fd = accept(sockfd, 117 (struct sockaddr*)&clientaddr, 118 &clientaddr_len); 119 if(fd < 0) 120 { 121 perror("accept error"); 122 continue; 123 } 124 /* 125 * 步骤5:调用I/O函数(read/write)和 126 * 连接的刻苦端进行双向的通信 127 */ 128 out_addr(&clientaddr); 129 do_server(fd); 130 131 /* 步骤6:关闭socket*/ 132 close(fd); 133 } 134 return 0; 135 }
客户端程序
#include <netdb.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <memory.h> #include <unistd.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { if(argc < 3) { printf("usage: %s ip port",argv[0]); exit(1); } /*步骤1:创建socket*/ int sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) { perror("socket error"); exit(1); } struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(atoi(argv[2])); //将ipo地址转换成网络字节序后填入serveraddr中 inet_pton(AF_INET,argv[1], &serveraddr.sin_addr.s_addr); /* * 步骤2:客户端调用connect函数连接到服务器端 */ if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) { perror("connect error"); exit(1); } /*步骤3:调用IO函数和服务器端进行双向通信*/ char buffer[1024]; memset(buffer, 0, sizeof(buffer)); size_t size; if((size = read(sockfd, buffer,sizeof(buffer))) < 0) { perror("read error"); } if(write(STDOUT_FILENO, buffer, size) != size) { perror("write error"); } return 0; }