功能介绍

  1. 客户端:登陆及注册;列出当前在线用户列表、发送聊天消息、传输文件等。
  2. 服务端:记录注册及在线用户链表、记录用户聊天数据、显示用户的登陆退出等。

主要知识点:socket套接字、链表用户管理、线程创建管理、IO复用、select监听套接字、文件读写等。


程序下载

https://download.csdn.net/download/mrhjlong/10337335


服务端主函数代码:client.c

/*************************************************************************> File Name: client.c> Author: mrhjlong> Mail: mrhjlong@163.com > Created Time: 2016年08月01日 星期一 14时40分39秒************************************************************************/#include "userlist.h"void *func_ttl(void *arg)
{int fd = (int)arg;while(1){cli_TTL(fd);sleep(20);}return NULL;
}int main(int argc, char *argv[])
{   int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0)err_sys("socket error");struct sockaddr_in des_addr;des_addr.sin_family = AF_INET;des_addr.sin_port = htons(9999);inet_pton(AF_INET, "127.0.0.1", &des_addr.sin_addr);//连接客户端int ret = connect(fd, (struct sockaddr *)&des_addr, sizeof(des_addr));if(ret == -1)err_sys("connect error");//登陆和注册登陆ret = cli_REG_LOG(fd);if(ret == -1)   //放弃登陆或注册,直接退出{close(fd);return 0;}//创建线程发送保活信息pthread_t pid;ret = pthread_create(&pid, NULL, func_ttl, (void *)fd);if(ret != 0)err_sys("pthread create error");MSG msgdata;fd_set read_set;int n;int flag = 0;char recv_buf[BUFSIZE] = {0};char fname[50] = {0};while(1){FD_ZERO(&read_set);if(flag == 0){printf("Input a command: s-send | f-file | l-list | q-quit...\n");FD_SET(0, &read_set);}FD_SET(fd, &read_set);select(fd + 1, &read_set, NULL, NULL, NULL);if(FD_ISSET(0, &read_set))  //输入响应{bzero(&msgdata, sizeof(msgdata));fgets(msgdata.cmd, 50, stdin);if(strcmp(msgdata.cmd, "q\n") == 0) //退出{pthread_cancel(pid);    //关闭线程flag = 1;shutdown(fd, SHUT_WR);FD_CLR(0, &read_set);continue;}else if(strcmp(msgdata.cmd, "l\n") == 0)    //发送命令,列出当前在线用户{cli_LIST(fd);continue;}else if(strcmp(msgdata.cmd, "s\n") == 0){cli_SEND(fd, &msgdata);}else if(strcmp(msgdata.cmd, "f\n") == 0)    //发送FILE命令{bzero(fname, 50);ret = cli_FILE(fd, &msgdata, fname);if(ret == 0)flag = 1;continue;}else{printf("#################WARNING#################\n");printf("Input error! Please try again!\n");printf("#########################################\n");continue;}}if(FD_ISSET(fd, &read_set))     //接收信息{bzero(recv_buf, BUFSIZE);bzero(&msgdata, sizeof(msgdata));n = recv(fd, recv_buf, BUFSIZE, 0);if(n == 0)      //关闭{printf("closed!\n");break;}read_XML(recv_buf, &msgdata);if(strcmp(msgdata.cmd, "LISTD") == 0){printf("**************Online users:**************\n");printf("%s\n", msgdata.text);printf("*****************************************\n");continue;}else if(strcmp(msgdata.cmd, "RECV") == 0){printf("*****************RECV...*****************\n");printf("FROM:%s\n", msgdata.name);printf("MSG:%s\n", msgdata.text);printf("*****************************************\n");}else if(strcmp(msgdata.cmd, "NOUSR") == 0){printf("#################WARNING#################\n");printf("User:%s is offline! Please try later.\n", msgdata.text);printf("#########################################\n");flag = 0;}else if(strcmp(msgdata.cmd, "LEAVE") == 0){pthread_cancel(pid);    //关闭线程printf("cmd closed!\n");break;}else if(strcmp(msgdata.cmd, "FCNT") == 0)   //建立传输文件连接,发送{cli_FCNT(&msgdata, fname);flag = 0;}else if(strcmp(msgdata.cmd, "FLSN") == 0)   //建立传输文件监听, 接收信息{cli_FLSN(fd, &msgdata);}}}close(fd);return 0;
}

服务端主函数代码:server.c

/*************************************************************************> File Name: server.c> Author: mrhjlong> Mail: mrhjlong@163.com > Created Time: 2016年08月01日 星期一 14时13分10秒************************************************************************/#include "userlist.h"int main(void)
{struct list_head list;  //新建在线用户链表INIT_LIST_HEAD(&list);  //初始化链表头struct list_head usrList;   //新建已注册用户链表 INIT_LIST_HEAD(&usrList);FILE *fp = fopen("regUser.txt", "r");if(fp == NULL)err_sys("open regUser.txt error!\n");//获取已注册用户链表get_user_list(fp, &usrList);    int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0)err_sys("socket error");int optval = 1;int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));if(ret == -1)err_sys("setsockopt error!");//服务器地址端口设置struct sockaddr_in my_addr;my_addr.sin_family = AF_INET;my_addr.sin_port = htons(9999);my_addr.sin_addr.s_addr = htonl(INADDR_ANY);//绑定服务器ret = bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));if(ret != 0)err_sys("bind error");//监听ret = listen(sockfd, 10);if(ret != 0)err_sys("listen error");printf("listening...\n");fd_set read_set;MSG msgdata;char recv_buf[BUFSIZE] = {0};int n;struData_t *p = NULL;struct list_head *pos = NULL;struct timeval timeout;LD ldata;while(1){FD_ZERO(&read_set);FD_SET(sockfd, &read_set);FD_SET(0, &read_set);//遍历链表,添加套接字到selectlist_for_each(pos, &list){p = list_entry(pos, struData_t, list);FD_SET(p->sockfd, &read_set);}//设置selecttimeout.tv_sec = 3;     //阻塞3秒timeout.tv_usec = 0;if(pos->prev == &list)ret = select(sockfd + 1, &read_set, NULL, NULL, &timeout);else{p = list_entry(pos->prev, struData_t, list);ret = select(p->sockfd + 1, &read_set, NULL, NULL, &timeout);}//超时返回,检测客户保活信息if(ret == 0)        {chk_ttl(&list);continue;}//服务端退出if(FD_ISSET(0, &read_set)){char cmd_quit[50] = {0};fgets(cmd_quit, 50, stdin);if(strcmp(cmd_quit, "q\n") == 0)    //输入q退出{ser_quit(&usrList, &list);printf("Closing server!\n");break;}else if(strcmp(cmd_quit, "s\n") == 0)   //输入s显示聊天记录{FILE *fp = fopen("Chatlog.txt", "r");char buffer[100] = {0};if(fp == NULL)printf("open Chatlog.txt error!\n");printf("*****************Chat record:******************\n");fgets(buffer, 100, fp);while(strlen(buffer) >= 8){printf("%s", buffer);bzero(buffer, 100);fgets(buffer, 100, fp);}printf("***********************************************\n");}else if(strcmp(cmd_quit, "l\n") == 0)   //输入l获取已注册用户信息{FILE *fp = fopen("regUser.txt", "r");if(fp == NULL)err_sys("open regUser.txt error!\n");//获取已注册用户链表get_user_list(fp, &usrList);}elseprintf("Input error! Please try again!\n");continue;}//监听套接字响应if(FD_ISSET(sockfd, &read_set)) {   ldata.sockfd = sockfd;ldata.usrList = &usrList;ldata.list = &list;//创建处理注册和登陆操作的线程pthread_t pid;int n = pthread_create(&pid, NULL, listen_reg_log, (void *)&ldata);if(n != 0)err_sys("pthread create error");n = pthread_detach(pid);if(n != 0)err_sys("pthread detach error");usleep(200);    //等待线程accept,否则会重复创建线程ret--;}//客户端套接字响应,接收到信息if(ret > 0)                         {//遍历链表,找到响应的套接字list_for_each(pos, &list)       {p = list_entry(pos, struData_t, list);if(FD_ISSET(p->sockfd, &read_set))break;}bzero(recv_buf, BUFSIZE);n = recv(p->sockfd, recv_buf, BUFSIZE, 0);//客户端主动关闭,服务端释放内存if(n == 0)      {printf("User:%s is leaving...\n", p->client_name);close(p->sockfd);list_del(pos);free(p);continue;}bzero(&msgdata, sizeof(msgdata));read_XML(recv_buf, &msgdata);   //解析XML数据if(strcmp(msgdata.cmd, "LIST") == 0)        //LIST命令处理{ser_LIST(p->sockfd, &list, &msgdata);continue;}else if(strcmp(msgdata.cmd, "TTL") == 0)    //TTL命令处理{time(&(p->ttl));    //重置保活时间continue;}else if(strcmp(msgdata.cmd, "SEND") == 0)   //SEND命令处理{ser_SEND(p->sockfd, p->client_name, &list, &msgdata);continue;}else if(strcmp(msgdata.cmd, "FILE") == 0){ser_FILE(p->sockfd, p->client_name, &list, &msgdata);}}   }close(sockfd);return 0;
}

Linux局域网多人聊天软件相关推荐

  1. linux socket 多人聊天软件,Linux Socket编程---TCP实现多客户端的网络聊天室

    #include//打开文件 int fd; //客户端socket int client_sock; //文件路径 char path[100]; //段口号 char port[100]; //发 ...

  2. linux下多人聊天室

    客户端 一个在Linux下可以使用的聊天软件,要求至少实现如下功能:1. 采用Client/Server架构2. Client A 登陆聊天服务器前,需要注册自己的ID和密码3. 注册成功后,Clie ...

  3. 使用jrtp与opus构建的windows局域网多人聊天dll

    使用jrtp与opus构建的局域网多人聊天dll Github 简介 函数说明 注意!! 额外 Github https://github.com/HaHaHaHaHaGe/Multi-person- ...

  4. linux下udp实现聊天软件,socket实现一个简单的对话聊天软件

    socket可以在网络间进行通信, 基本上有两种通信协议, 一种是TCP, 一种是UDP. UDP是一种面向无链接的通信协议, 通信前无需与对端建立连接. 只要有目的ip地址和port端口, 就可以将 ...

  5. Linux 下 c 语言 聊天软件

    这是我学C语言写的第一个软件,是一个完整的聊天软件,里面包括客户端,和服务器端,可以互现聊天,共享文件,有聊天室等,是一个有TCP和UDP协议的聊天软件,测试过很多次在CENTOS和UBUNTU下都通 ...

  6. linux程序多人聊天室,【linux】多人聊天室实现

    一.设计思路 服务器接收来自客户端的连接请求,当有客户端发送过来数据时, 服务器将数据保存到全局缓冲区,并将数据循环发送给已经连接的客户端 二.代码展示 1.  服务器端charroom_server ...

  7. Linux最佳聊天软件:Skype 4.3轻体验

    Linux最佳聊天软件:Skype 4.3轻体验 自从 2012 年 4 月坚持使用 Linux 单系统以来,对于山寨王腾孙的做派极为厌恶.而自身已没有非要 QQ 不可的场合,所以彻底转向了 Skyp ...

  8. 局域网聊天软件 设计文档怎么写?

    局域网聊天软件 设计文档怎么写?这种针对数据库记录的 局域网聊天软件 窃取,被一些攻击者称为拖库,于是有了一个自然而谐音的戏称脱裤.只是攻击者日趋不厚道,从前只是偷了人家的裤子,现在还要晾在大街上,并 ...

  9. linux局域网语音通讯软件下载,基于Linux平台的局域网可语音的IM软件的设计与实现.doc...

    基于Linux平台的局域网可语音的IM软件的设计与实 作者: 专业:软件工程 指导老师: 摘要 随着计算机网络的日益普及人们通过网络进行交流显得越来越重要.于是出现了一系列的通信软件. 自1990s ...

  10. 局域网聊天软件都有哪些?几款常用的局域网聊天软件推荐

    随着科技的不断发展,人们在日常生活和工作中越来越需要高效便捷的沟通工具.而局域网聊天软件就是一种在局域网内使用的聊天工具,它能够帮助用户在同一网络内的设备之间进行即时通讯,无需依赖于互联网连接,安全又 ...

最新文章

  1. https 证书验证等原理
  2. php和python web开发-初入Web开发,php、python和ruby应该学哪个?
  3. 左耳朵耗子:程序员如何把控自己的职业?
  4. Uncaught TypeError: Cannot read property 'style' of null
  5. [BZOJ3214][ZJOI2013]丽洁体(Hash+DP)
  6. WinPcap 获取本地适配器信息
  7. 初步认识Volatile-一段代码引发的思考
  8. MySQL中my.cnf解析
  9. python生成二维坐标点_Python numpy:根据坐标创建二维数组
  10. mysql sync es 异步双写_mysql数据同步es方案思考
  11. bochs运行xp_bochs xp镜像下载-bochs xp镜像下载 v2.5.1精简版-下载啦
  12. Ubuntu18.04 wifi不稳定
  13. DDD(领域驱动设计)系列主题:DDD战略设计和战术设计分析流程及关键输出物
  14. NO_PROXY is not set
  15. k8s学习-污点和容忍(概念、模版、创建、删除)
  16. bbr是什么?有什么用?如何安装使用?
  17. STM32F407VET6的OTM8009_800X480屏幕驱动移植
  18. mysql的strict_MySQL Strict SQL MODE
  19. 【学习率】梯度下降学习率的设定策略
  20. 基于51单片机的智能煤气天然气CO检测阈值报警器排气风扇方案原理图设计

热门文章

  1. Abaqus槽钢杆受力有限元分析
  2. 云栖号在线课堂—云服务器数据库快速入门特辑
  3. BAT4行代码让电脑蓝屏(无伤害)
  4. 关于Nginx跨域配置的一些问题,详解如何正确的配置跨域
  5. 南京邮电大学 RE-WxyVM
  6. 一位北美 IT 技术人教你如何破局
  7. C语言入门130题-OJ
  8. Excel 公式学习笔记:数组用法
  9. ssh远程连接Ubuntu 20.04
  10. android手机的屏幕录制在哪里,手机屏幕录制在哪里,安卓手机视频录制软件分享...