最近学习网络编程,写了一个聊天室,基本功能已经实现,还有待优化的部分
服务器端
#include"server.h" static int sockid,i,end; void fa(int signo) { printf("\r服务器正在关闭>>>>>\n"); sleep(2); close(sockid); exit(0); } typedef struct { struct sockaddr_in c_sockaddr; int c_sockid; pthread_t tid; }c_addr; //建立套接字绑定端口 int s_bind(void); int s_pthread_create(int sockid); void * task(void *p); int main(int argc,char * agrv[]) { printf("服务器开始运行\n"); //信号处理 signal(2,fa); //建立套结字,绑定借口 int sockid = s_bind(); if(-1 == sockid) printf("建立绑定套结字失败\n"); //开始监听客户端 listen(sockid,100); //为客户端分配线程 s_pthread_create(sockid); //exit(0); exit(0); } int s_bind(void) { //生成套结字 sockid = socket(AF_INET,SOCK_STREAM,0); //准备地址信息 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //绑定服务短地址 int res = bind(sockid,(struct sockaddr *)&addr,sizeof(addr)); if(res == -1) { perror("bind"),exit(-1);; } return sockid; } int s_pthread_create(int sockid) { //定义结构题,用于存储客户端的地址与通信编号 c_addr c_c_addr[100]; while(i < 100){ //初始化c_c_addr c_c_addr[i].c_sockid = 0; //准备套结字接收客户端地址 socklen_t len = sizeof(c_c_addr[i].c_sockaddr); //接受到客户端信息 c_c_addr[i].c_sockid = accept(sockid,(struct sockaddr *)&c_c_addr[i].c_sockaddr,&len); if(c_c_addr[i].c_sockid == -1) perror("accept"),exit(-1); //分配线程 //pthread_t tid; printf("客户端:%s上线\n",inet_ntoa(c_c_addr[i].c_sockaddr.sin_addr)); pthread_create(&c_c_addr[i].tid,NULL,task,(void *)c_c_addr); usleep(500000); i++; } } void * task(void *p) { int n = i; c_addr * c_c_addr = p; //接收客户端发来的消息 char buf[100] = {0}; while(1) { printf("n == %d\n",n); if(0 >= read(c_c_addr[n].c_sockid,buf,sizeof(buf))) { c_c_addr[n].c_sockid = -1; printf("客户端:%s下线\n",inet_ntoa(c_c_addr[n].c_sockaddr.sin_addr)); pthread_exit(&c_c_addr[n].tid); } printf("来自客户端的消息%s\n",buf); char *p = buf; //转发给其他客户端 int j = 0; while(j < i) { //判断是否是自己线程, if(c_c_addr[j].tid == pthread_self() || c_c_addr[j].c_sockid == -1) { j++; continue; } if(0 >= send(c_c_addr[j].c_sockid,buf,strlen(buf) + 1,0)) { c_c_addr[j].c_sockid = -1; } j++; } //推出线程 } }
客户端
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<netinet/in.h> #include<arpa/inet.h> #include<semaphore.h> #include<sys/socket.h> #include<sys/types.h> #include<pthread.h> #include<unistd.h> #define PORT 8888 int sockid; void fa(int signo) { printf("\r客户端马上关闭\n"); close(sockid); sleep(1); exit(0); } int c_connect(void); void scan(char arr[]); void talk(void); void *task(void *p); void speak(char *name); int main() { signal(2,fa); //与服务器建立链接 sockid = c_connect(); //输入用户昵称 char name[20]; printf("请输入用户姓名\n"); scanf("%s",name); //接收服务器发来的消息 talk(); //吧用户输入的信息发送给服务器端 speak(name); } void speak(char *name) { while(1) { //sleep(1); printf("请输入信息:\n"); char cuf[100]; fflush(stdin); //scanf("%*[^\n]"); //scanf("%*c"); //fwrite(cuf,1,1,stdin); scanf("%s",cuf); // fgets(cuf,100,stdin); fflush(stdin); //cuf[strlen(cuf)-1] = '\0'; char buf[1000]; sprintf(buf,"%s:%s",name,cuf); int res; if( 0 >= send(sockid,buf,strlen(buf) + 1,0)) //printf("res = %d\n",res); perror("服务器关闭"),exit(-1); } } void *task(void *p) { char buf[100]; while(1) { if(0 > recv(sockid,buf,sizeof(buf),0)) perror("recv"),exit(0); printf("%s\n",buf); } } void talk(void) { //创建线程用于接受服务器的消息 pthread_t tid; pthread_create(&tid,NULL,task,NULL); } void scan(char arr[]) { printf("请输入用户昵称\n"); scanf("%s",arr); fflush(stdin); } int c_connect(void) { int sockid = socket(AF_INET,SOCK_STREAM,0); //准备服务器的地址信息 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8888); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //链接服务器地址 int res = connect(sockid,(struct sockaddr*)&addr,sizeof(addr)); if(-1 == res) { perror("connect"),exit(-1); } return sockid; }