2.2 TCP协议下实现两人聊天
head.h
1 //TCP协议下实现两人聊天 2 #ifndef _HEAD_H_ 3 #define _HEAD_H_ 4 5 #include <stdio.h> 6 #include<stdlib.h> 7 #include<string.h> 8 #include<error.h> 9 #include<errno.h> 10 #include<sys/types.h> 11 #include<sys/socket.h> 12 #include<netinet/in.h> 13 #include<netinet/ip.h> 14 #include<arpa/inet.h> 15 #include<signal.h> 16 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_) 17 #define SER_PORT 50000 18 #define SER_ADDR "192.168.239.129" 19 20 #endif
Makefile
1 ALL:client server 2 client:client.c 3 gcc $< -o $@ 4 server:server.c 5 gcc $< -o $@ 6 7 clean: 8 rm client server
client.c
1 #include"head.h" 2 int main()//client 3 { 4 int sockfd=0; 5 char buff[1024]={0}; 6 struct sockaddr_in seraddr; 7 seraddr.sin_family=AF_INET; 8 seraddr.sin_port=htons(SER_PORT); 9 seraddr.sin_addr.s_addr=inet_addr(SER_ADDR); 10 //创建一个用来通信的文件描述符 11 if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))) 12 error_exit("fail to socket!"); 13 //发送一个链接请求,有绑定功能 14 if(-1==connect(sockfd,(struct sockaddr* )&seraddr,sizeof(seraddr))) 15 error_exit("fail to connect!"); 16 //创建父子进程 17 pid_t pid,pid1; 18 if(-1==(pid=fork())) 19 error_exit("fail to fork!"); 20 if(pid==0)//子进程负责发送 21 { 22 while(1) 23 { //从终端读取数据到buff/ fgets 读到字符串尾加'\0' 24 fgets(buff,sizeof(buff),stdin); 25 //send 无绑定功能,不绑定客户端自己的IP地址和端口号发送出去的。 26 if(-1==send(sockfd,buff,strlen(buff)+1,0)) 27 error_exit("fail to send!"); 28 if(!strncmp(buff,"quit",4))break;//发quit退出 29 } 30 pid1=getppid(); 31 } 32 else if(pid>0)//父进程负责接收 33 { 34 while(1) 35 { 36 //收到服务器端回复,可以不显示对方IP地址,recv有阻塞功能 37 if(-1==recv(sockfd,buff,sizeof(buff),0)) 38 error_exit("fail to recv!"); 39 //printf("%s:%d-->buff=%s\n",inet_ntoa(cltaddr.sin_addr), 40 // ntohs(cltaddr.sin_port),buff); 41 if(!strncmp(buff,"quit",4))break; 42 printf("RECV:%s",buff);//接收显示 43 } 44 pid1=pid; 45 } 46 kill(pid1,SIGKILL);//杀死父子进程 47 close(sockfd);//关闭套接字文件描述符 48 return 0; 49 }
server.c
1 #include"head.h" 2 int main()//server 3 { 4 int sockfd=0; 5 int confd=0; 6 char buff[1024]={0}; 7 struct sockaddr_in seraddr; 8 seraddr.sin_family=AF_INET; 9 seraddr.sin_port=htons(SER_PORT); 10 seraddr.sin_addr.s_addr=inet_addr(SER_ADDR); 11 //创建一个用来通信的文件描述符 12 if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))) 13 error_exit("fail to socket!"); 14 //将sockfd和IP地址绑定 15 if(-1==bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr)))//socklen_t addrlen; 16 error_exit("fail to bind!"); 17 //指定链接请求队列的长度,listen无阻塞功能 18 if(-1==listen(sockfd,10)) 19 error_exit("fail to listen!"); 20 //与链接请求队列中第一个链接请求建立TCP握手,accept有阻塞等待功能 21 if(-1==(confd=accept(sockfd,NULL,NULL))) 22 error_exit("fail to accept!"); 23 //创建父子进程 24 pid_t pid,pid1; 25 if(-1==(pid=fork())) 26 error_exit("fail to fork!"); 27 if(pid==0)//子进程负责发送 28 { 29 while(1) 30 { //从终端读取数据到buff/ fgets 读到字符串尾加'\0' 31 fgets(buff,sizeof(buff),stdin); 32 //send 无绑定功能,不绑定客户端自己的IP地址和端口号发送出去的。 33 if(-1==send(confd,buff,strlen(buff)+1,0)) 34 error_exit("fail to send!"); 35 if(!strncmp(buff,"quit",4))break;//发quit退出 36 } 37 pid1=getppid(); 38 } 39 else if(pid>0)//父进程负责接收 40 { 41 while(1) 42 { 43 //收到客户端信息,可以不显示对方IP地址,recv有阻塞功能 44 if(-1==recv(confd,buff,sizeof(buff),0)) 45 error_exit("fail to recv!"); 46 //printf("%s:%d-->buff=%s\n",inet_ntoa(cltaddr.sin_addr), 47 // ntohs(cltaddr.sin_port),buff); 48 if(!strncmp(buff,"quit",4))break; 49 printf("RECV:%s",buff);//接收显示 50 } 51 pid1=pid; 52 } 53 kill(pid1,SIGKILL);//杀死父子进程 54 close(sockfd);//关闭套接字文件描述符 55 close(confd);//关闭各子进程文件描述符 56 return 0; 57 }

浙公网安备 33010602011771号