300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 利用C语言编写简易的网络聊天室

利用C语言编写简易的网络聊天室

时间:2020-11-17 22:52:33

相关推荐

利用C语言编写简易的网络聊天室

网络聊天室

业务逻辑:

1、客户端注册名字

2、告诉所有在线的客户端,XXX进入聊天室

3、新建一个线程为该客户端服务,随时接收客户端发送来的消息

4、当接收到一个客户端的消息时,向每一个客户端转发一份(群聊)

5、同时在线人数最多50人

任何客户端可以随意随时进入或退出客户端

服务端代码server.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <pthread.h>#include <semaphore.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#ifndef DEBUG#define debug(format,...) {}#else#define debug(format,...) \{\fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\fprintf(stdout,format,##__VA_ARGS__);\fprintf(stdout,"\n");\}#endif//DEBUG#define error(format,...)\{\fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\fprintf(stdout,format,##__VA_ARGS__);\fprintf(stdout,":%m\n");\exit(EXIT_FAILURE);\}// 客户端最大连接数#define CLIENT_MAX 50// 服务器端口号#define PORT 5566// 缓冲区大小#define BUF_SIZE 4096// 重定义socket地址类型typedef struct sockaddr* SP;// 客户端结构体typedef struct Client{int sock;//socket 标识符pthread_t tid; //线程IDchar name[20];struct sockaddr_in addr;}Client;// 定义50个存储客户端的结构变量Client clients[50];// 定义信号量用于限制客户端的数量sem_t sem;// 信号处理函数void sigint(int num){for(int i=0; i<10; i++){if(clients[i].sock){pthread_cancel(clients[i].tid);//销毁线程}}debug("服务器退出!");exit(EXIT_SUCCESS);}void client_eixt(Client* client){sem_post(&sem);close(client->sock);client->sock = 0;}void client_send(Client* client,char* buf){size_t len = strlen(buf)+1;for(int i=0; i<CLIENT_MAX; i++){if(clients[i].sock && clients[i].sock != client->sock){send(clients[i].sock,buf,len,0);}}}void* run(void* arg){Client* client = arg;char buf[BUF_SIZE] = {};// 接收昵称int ret_size = recv(client->sock,client->name,20,0);if(0 >= ret_size){client_eixt(client);return NULL;}// 通知其它客户端新人上线sprintf(buf,"!!!欢迎%s进入聊天室!!!",client->name);client_send(client,buf);for(;;){// 接收消息ret_size = recv(client->sock,buf,BUF_SIZE,0);if(0 >= ret_size || 0 == strcmp("quit",buf)){// 通知其它客户端退出sprintf(buf,"!!!%s退出聊天室!!!",client->name);client_send(client,buf);client_eixt(client);return NULL;}strcat(buf,":");strcat(buf,client->name);client_send(client,buf);debug(buf);}}int main(int argc,const char* argv[]){signal(SIGINT,sigint);debug("注册信号处理函数成功!");sem_init(&sem,0,CLIENT_MAX);debug("初始化信号量成功!");int svr_sock = socket(AF_INET,SOCK_STREAM,0);if(0 > svr_sock){error("socket");}debug("创建socket对象成功!");struct sockaddr_in svr_addr = {};svr_addr.sin_family = AF_INET;svr_addr.sin_port = htons(PORT);svr_addr.sin_addr.s_addr = INADDR_ANY;socklen_t addrlen = sizeof(svr_addr);debug("准备通信地址成功!");if(bind(svr_sock,(SP)&svr_addr,addrlen)){error("bind");}debug("绑定socket对象和通信地址成功!");if(listen(svr_sock,10)){error("listen");}debug("设置监听socket监听成功!");for(;;){debug("等待客户端连接...");sem_wait(&sem);int index = 0;while(clients[index].sock){index++;}clients[index].sock = accept(svr_sock,(SP)&clients[index].addr,&addrlen);if(0 > clients[index].sock){kill(getpid(),SIGINT);}debug("有新的客户端连接,from ip:%s",inet_ntoa(clients[index].addr.sin_addr));pthread_create(&clients[index].tid,NULL,run,&clients[index]);}}

客户端代码client.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <pthread.h>#include <semaphore.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#ifndef DEBUG#define debug(format,...) {}#else#define debug(format,...) \{\fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\fprintf(stdout,format,##__VA_ARGS__);\fprintf(stdout,"\n");\}#endif//DEBUG#define error(format,...)\{\fprintf(stdout,"%s:%d:%s ",__func__,__LINE__,__TIME__);\fprintf(stdout,format,##__VA_ARGS__);\fprintf(stdout,":%m\n");\exit(EXIT_FAILURE);\}#define BUF_SIZE 4096#define SERVER_PORT 5566#define SERVER_IP "192.168.0.125"typedef struct sockaddr* SP;void* run(void* arg){int cli_sock = *(int*)arg;char buf[BUF_SIZE] = {};for(;;){int ret_size = recv(cli_sock,buf,BUF_SIZE,0);if(0 >= ret_size){printf("服务器正在升级,请稍候登录!\n");exit(EXIT_SUCCESS);}printf("\r%30s\n>>>",buf);fflush(stdout);}}int main(int argc,const char* argv[]){int cli_sock = socket(AF_INET,SOCK_STREAM,0);if(0 > cli_sock){error("socket");}struct sockaddr_in cli_addr= {};cli_addr.sin_family = AF_INET;cli_addr.sin_port = htons(SERVER_PORT);cli_addr.sin_addr.s_addr = inet_addr(SERVER_IP);socklen_t addrlen = sizeof(cli_addr);if(connect(cli_sock,(SP)&cli_addr,addrlen)){printf("服务器正在升级,请稍候登录!\n");return EXIT_SUCCESS;}char buf[BUF_SIZE] = {};printf("请输入你的眤称:");gets(buf);send(cli_sock,buf,strlen(buf)+1,0);pthread_t tid;pthread_create(&tid,NULL,run,&cli_sock);for(;;){printf(">>>");gets(buf);send(cli_sock,buf,strlen(buf)+1,0);if(0 == strcmp("quit",buf)){printf("退出聊天室!\n");return EXIT_SUCCESS;}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。