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 }

 

posted @ 2017-03-13 21:22  bkycrmn  阅读(266)  评论(0)    收藏  举报