商业网站设计与制作,重庆市建设工程信息网安全,怎么免费注册企业邮箱,用wordpress还是php转载#xff1a;http://blog.csdn.net/robot__man/article/details/52460733 要求#xff1a;基于TCP编写#xff0c;一个聊天室最多100人。 客户端#xff1a; 1、用户需要登录#xff0c;登录时只需要输入一个昵称即可无需判断昵称是否重复#xff08;如果其他功…转载http://blog.csdn.net/robot__man/article/details/52460733 要求基于TCP编写一个聊天室最多100人。 客户端 1、用户需要登录登录时只需要输入一个昵称即可无需判断昵称是否重复如果其他功能都ok考虑 2、用户登录后连接服务器端进入聊天室 3、用户可以输入聊天信息也可以收到别人的聊天信息。 4、用户可以用某个特殊单词代表退出聊天室。 服务器端 1、启动服务器开放端口 2、等待客户端的连接每连接上一个客户端启动一个线程 3、在线程中与客户端交互交互过程如果有客户端登录、退出、提交聊天都应该发给所有的客户端。需要 保存所有客户端。 额外功能可以考虑实现TCP的文件传输。
server.c#include stdio.h
#include string.h
#include stdlib.h
#include unistd.h
#include netinet/in.h
#include arpa/inet.h
#include sys/socket.h
#include pthread.hint sockfd;//服务器socket
int fds[100];//客户端的socketfd,100个元素fds[0]~fds[99]
int size 100 ;//用来控制进入聊天室的人数为100以内
char* IP 192.168.10.143;
short PORT 10222;
typedef struct sockaddr SA;void init(){sockfd socket(PF_INET,SOCK_STREAM,0);if (sockfd -1){perror(创建socket失败);exit(-1);}struct sockaddr_in addr;addr.sin_family PF_INET;addr.sin_port htons(PORT);addr.sin_addr.s_addr inet_addr(IP);if (bind(sockfd,(SA*)addr,sizeof(addr)) -1){perror(绑定失败);exit(-1);}if (listen(sockfd,100) -1){perror(设置监听失败);exit(-1);}
}void SendMsgToAll(char* msg){int i;for (i 0;i size;i){if (fds[i] ! 0){printf(sendto%d\n,fds[i]);send(fds[i],msg,strlen(msg),0);}}
}void* service_thread(void* p){int fd *(int*)p;printf(pthread %d\n,fd);while(1){char buf[100] {};if (recv(fd,buf,sizeof(buf),0) 0){int i;for (i 0;i size;i){if (fd fds[i]){fds[i] 0;break;}}printf(退出fd %dquit\n,fd);pthread_exit((void*)i);}//把服务器接受到的信息发给所有的客户端SendMsgToAll(buf);}
}void service(){printf(服务器启动\n);while(1){struct sockaddr_in fromaddr;socklen_t len sizeof(fromaddr);int fd accept(sockfd,(SA*)fromaddr,len);if (fd -1){printf(客户端连接出错...\n);continue;}int i 0;for (i 0;i size;i){if (fds[i] 0){//记录客户端的socketfds[i] fd;printf(fd %d\n,fd);//有客户端连接之后启动线程给此客户服务pthread_t tid;pthread_create(tid,0,service_thread,fd);break;}if (size i){//发送给客户端说聊天室满了char* str 对不起聊天室已经满了!;send(fd,str,strlen(str),0); close(fd);}}}
}int main(){init();service();
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
client.c#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include pthread.hint sockfd;//客户端socket
char* IP 192.168.10.143;//服务器的IP
short PORT 10222;//服务器服务端口
typedef struct sockaddr SA;
char name[30];void init(){sockfd socket(PF_INET,SOCK_STREAM,0);struct sockaddr_in addr;addr.sin_family PF_INET;addr.sin_port htons(PORT);addr.sin_addr.s_addr inet_addr(IP);if (connect(sockfd,(SA*)addr,sizeof(addr)) -1){perror(无法连接到服务器);exit(-1);}printf(客户端启动成功\n);
}void start(){pthread_t id;void* recv_thread(void*);pthread_create(id,0,recv_thread,0);char buf2[100] {};sprintf(buf2,%s进入了聊天室,name);send(sockfd,buf2,strlen(buf2),0);while(1){char buf[100] {};scanf(%s,buf);char msg[131] {};sprintf(msg,%s:%s,name,buf);send(sockfd,msg,strlen(msg),0);if (strcmp(buf,bye) 0){memset(buf2,0,sizeof(buf2));sprintf(buf2,%s退出了聊天室,name);send(sockfd,buf2,strlen(buf2),0);break;}}close(sockfd);
}void* recv_thread(void* p){while(1){char buf[100] {};if (recv(sockfd,buf,sizeof(buf),0) 0){return;}printf(%s\n,buf);}
}int main(){init();printf(请输入您的名字);scanf(%s,name);start();return 0;
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 刚开始我声明的那个全局数组int fds[99],它是有99个元素fds[0]~fds[98],我以为是到fds[99]结果数组越界向fds[99]指向的未知文件描述符发了个数据而fds[99]指向的是监视进程的向它发任何数据进程都会莫名奇妙的终止。于是服务器莫名奇妙的挂掉了朋友用gdb调试才发现Program received signal SIGPIPE, Broken pipe.这个问题我自己看了一天半也没发现最后还是在群里面别人帮提出来的感悟有以下几点 1、Linux下写程序也有调试工具gdb要学会使用程序出错了如果看不出来就可以来调试 2、程序员不是一直埋头写程序就行了还是要多和别人交流一切以解决问题为根本。