前文列表:
目的:
设计一个C/S程序,客户端发送/接收消息,服务端将从客户端接收到的消息群发给其它已连接套接字,产生
类似群聊的效果
相对于之前的改进:
1.客户端可以在服务端终止后得到通知
2.客户端使用shutdown()函数处理批量输入产生的问题
3.服务端使用select()函数管理套接字(单进程),而非使用fork()让每个子进程管理一个套接字(多进程)
select函数介绍
程序代码:
客户端:
1 #include "net.h" 2 3 int main(int argc, char **argv) 4 { 5 int sockfd; 6 7 if (argc != 3) 8 { 9 printf("Error arg! "); 10 exit(1); 11 } 12 13 printf("%s ", argv[2]); 14 15 sockfd = tcp_connect(argv[1], SERV_PORT); 16 printf("Success init, the connected socket is %d ", sockfd); 17 cli_io_select(sockfd, argv[2], stdin); 18 printf("End... "); 19 20 return 0; 21 }
4 // 建立一个TCP套接字(IPv4),并与给定主机端口连接,并返回连接后的套接字 5 int tcp_connect(char *ser_ip, int port) 6 { 7 int sockfd; 8 struct sockaddr_in servaddr; 9 10 if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 11 { 12 printf("Error socket! "); 13 exit(1); 14 } 15 16 bzero(&servaddr, sizeof(servaddr)); 17 servaddr.sin_family = AF_INET; 18 servaddr.sin_port = htons(port); 19 20 if (inet_pton(AF_INET, ser_ip, &servaddr.sin_addr) <= 0) 21 { 22 printf("Error inet_pton! "); 23 exit(1); 24 } 25 26 if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) 27 { 28 printf("Error connect! "); 29 exit(1); 30 } 31 32 return sockfd; 33 }
35 // 将一个字符串放到另一个字符串的头部,构造将用户名加到客户发送的消息中 36 // 不提供对字符串空间大小的检查 37 char *addStrHead(char *head, char *row) 38 { 39 int headLen, rowLen, i; 40 headLen = strlen(head); 41 rowLen = strlen(row); 42 43 for (i = headLen + rowLen; i >= 0; i--) 44 { 45 if (i > headLen) 46 { 47 row[i] = row[i - headLen - 1]; 48 } 49 else if (i == headLen) 50 { 51 row[i] = ':'; 52 } 53 else 54 { 55 row[i] = head[i]; 56 } 57 } 58 59 row[headLen + rowLen + 1] = '