双方聊天:
服务器demo:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main(int argc,char** argv){
int s_fd,c_fd,fd;
int c_len;
char buf[1024] = {0};
char msg[1024] = {0};
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
if(argc != 3){
printf("Param wrong!\n");
exit(0);
}
//1.socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
//2.bind
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
int ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
if(ret == -1){
perror("bind");
exit(-2);
}
//3.listen
listen(s_fd,10);
//4.while(){ 1.accept 2.fork{1.read 2.write} }
while(1){
c_len = sizeof(struct sockaddr_in);
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_len);
if(c_fd == -1){
perror("accpet");
exit(-41);
}else{
printf("%s connected!\n",inet_ntoa(c_addr.sin_addr));
}
while(1){
fd = fork();
if(fd == 0){
while(1){
memset(msg,0,sizeof(msg));
gets(msg);
write(c_fd,msg,strlen(msg));
}
}
while(1){
memset(buf,0,sizeof(buf));
read(c_fd,buf,1024);
printf("New message:%s\n",buf);
}
}
}
return 0;
}
客户端demo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char** argv){
int c_fd,fd;
char msg[1024] = {0};
char buf[1024] = {0};
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
//1.socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
//2.connect
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
int ret = connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in));
if(ret == -1){
perror("connect");
exit(-2);
}
//3.while(1){fork 1.read 2.write}
while(1){
fd = fork();
if(fd == 0){
while(1){
memset(msg,0,sizeof(msg));
gets(msg);
write(c_fd,msg,strlen(msg));
}
}
while(1){
memset(buf,0,sizeof(buf));
read(c_fd,buf,1024);
printf("New message:%s\n",buf);
}
}
return 0;
}
~
运行结果:
这个练习最主要的思考点就是在需要创建另外一个进程,也是fork其中的一个功能:在网络进程中,通常使用两个进程,一个接受另一用户的数据,而一个要负责给对方发送数据。而接受数据的进程是时时刻刻都要进行,所以程序中,fork完没有判断是否是父进程还是子进程,所以一直在等待接受数据,而发送消息的行为是要在间歇时间完成,所以先判断是否为子进程,在子进程中完成。
至于多人聊天,因为gets需要输入,也会阻塞进程,所以资源就会被一直抢占,有时输入的时候,被子进程抢占了,接受数据的进程便无法运行,于是无法正常接受数据,而是会卡在client和server之间的管道中。目前解决方法是:不要gets,直接printf一段话可以简单模拟多人聊天;还有一种方式是几个client在聊天,通过server来中转消息(QQ和微信原理就是这个)