C语言实现简易网络聊天室
作者:菠萝小马哥
这篇文章主要为大家详细介绍了C语言实现简易网络聊天室,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了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; //线程ID char 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; } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。