网络聊天室
业务逻辑:
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;}}
}

利用C语言编写简易的网络聊天室相关推荐

  1. android socket 简易聊天室 java服务器_利用Socket制作一个简易的Android聊天室

    首先制作一个客户端,界面如下: 使用方法:启动后,首先在登录编辑框输入一个昵称,然后点击登录,上面灰色区域是聊天窗,其中会显示你的登录提示,显示其他人发的消息.在的登录成功后,可以在下面的发送编辑框内 ...

  2. 基于TCP的网络聊天室实现(C语言)

    基于TCP的网络聊天室实现(C语言) 一.网络聊天室的功能 二.网络聊天室的结果展示 三.实现思路及流程 四.代码及说明 1.LinkList.h 2.LinkList.c 3.client.c 4. ...

  3. java语言编写计算器_第二次作业利用java语言编写计算器进行四则运算

    随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ...

  4. 利用c语言编写一个时钟计时器(c语言基础练习)

    时间对于每个人都是宝贵的.人类从古至今都在发展计时设备和改善计时方法.远古时期,人类根据太阳和月亮的位置来判断时间.根据影子的方向长短来区分早晨.中午和黄昏.古代人也发明了很多计时的方法,日晷.沙漏. ...

  5. 利用Java语言编写一个猜数字游戏(有次数限制)

    猜数字小游戏. 利用Java语言编写. 题目: 用代码模拟猜数字的小游戏. 思路: 1.首先需要产生一个随机数字,并且一旦产生不再变化.用Random的nextInt方法 2.需要键盘输入,所以用到了 ...

  6. C语言实现网络聊天室 socket的简单应用

    C语言实现网络聊天室 socket的简单应用 前言:环境是Linux ,使用了 socket和pthread,主要分为服务器端和客户端两部分,服务器端监听端口发来的请求,收到后向客户端发送一个消息,客 ...

  7. [源码和文档分享]基于java语言的C/S模式网络聊天室软件

    一 需求分析 采用C/S模式,基于TCP协议编程的方式,使得各个用户通过服务器转发实现聊天的功能 分为三大模块:客户端模块.服务器端模块和公共辅助类模块 客户端模块的主要功能: 登陆功能:用户可以注册 ...

  8. linux 剪刀石头布c语言,利用C语言编写“剪刀石头布”小游戏

    前言 大家好~ 我是一名C语言初学者,学了C语言基础后,我制作了一个小游戏:剪刀石头布. 希望大家能对我的思路和代码提出小Tips(eg.更简便的方法与程序) 我也会虚心接受大家的建议~ 一.游戏原理 ...

  9. 易语言运行 (c:内部.exe, 假, ),利用易语言编写流氓软件

    首页 > 新闻动态 利用易语言编写流氓软件 编写流氓软件对于我们这样的没有怎么学过各种变成语言的人来说基本上是天方夜谭,但是今天我接触了一下易语言,发现它是-种对于我们小菜来说很容易上手的编程语 ...

最新文章

  1. Python数据集可视化:抽取数据集的两个特征进行二维可视化、主成分分析PCA对数据集降维进行三维可视化(更好地理解维度之间的相互作用)
  2. saltstack的安装(转载连接)
  3. ssl2290-潜水员【dp之二维费用】
  4. activemq端口好_ActiveMQ已准备好黄金时段
  5. 分享 2 个“捷径”,帮你 6 个月达到阿里 P7 水平
  6. Java面向对象知识总结
  7. 用一个URL加一个JAVA壳做成一个安卓应用
  8. mysql 附近3公里的,mysql 查询附近N公里内数据
  9. 红米pro android o刷机,红米Pro如何刷机?你可以通过这两种方法获取root权限!
  10. android中Zing二维码扫描,二维码生成
  11. Android 相机预览 横屏竖屏 -- 显示
  12. 微信网络营销 你造吗?
  13. 微信小程序打包的原理_说说微信小程序和它的打包加密算法
  14. 小程序/公众号商城一键生成工具之weiit-saas
  15. 大数据职业发展规划和技能
  16. 数字电路与C语言基础
  17. 变年轻特效是什么软件?快把这些软件收好
  18. 机票预订系统活动图_机票预订系统详细设计
  19. Win11 文件夹打开慢或卡顿解决方案
  20. 中国石油大学(北京)-《 油气田开发方案设计》第一阶段在线作业

热门文章

  1. 接口、抽象类和实现类
  2. face_recognition配置与安装
  3. AI观察 | 2020年中国人工智能产业规模将超万亿
  4. 练习|python格式化符号
  5. [日语二级词汇]日语二级必会汉字总结11
  6. 如何在3分钟内实现音频变声和趣味音效?
  7. 语音识别系列︱利用达摩院ModelScope进行语音识别+标点修复(四)
  8. python微信定时发消息_Python开发企业微信机器人每天定时发消息实例
  9. excel条件求和方法
  10. 怎么找到qq的人工客服!