服务器端的主要功能:

实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到。用户可以随意的加入或退出(推出以字符串“bye”实现),服务器也可以进行关闭。

服务器端的程序结构:

总共有三个函数:主函数(main),实现服务器端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息,将其进行简单处理之后发送给其他所有的用户;退出函数(quit),可实现服务器关停。

这三个函数分别从属于三个线程(准确说是大于等于三个,下面说明原因):main函数的作为诛仙程线程,又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程(多于三个的原因在此)。

具体代码实现如下:

  1. #include<time.h>
  2. #include<stdio.h>
  3. #include<sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<string.h>
  6. #define LISTENQ 5
  7. #define MAXLINE 512
  8. #define MAXMEM 10
  9. #define NAMELEN 20
  10. int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字
  11. void quit();//服务器关闭函数
  12. void rcv_snd(int n);//服务器接收并转发消息函数
  13. int main()
  14. {
  15. pthread_t thread;
  16. struct sockaddr_in servaddr,cliaddr;
  17. socklen_t len;
  18. time_t ticks;
  19. char buff[MAXLINE];
  20. //调用socket函数创建服务器端的套接字
  21. printf("Socket...\n");
  22. listenfd=socket(AF_INET,SOCK_STREAM,0);
  23. if(listenfd<0)
  24. {
  25. printf("Socket created failed.\n");
  26. return -1;
  27. }
  28. //调用bind函数使得服务器端的套接字与地址实现绑定
  29. printf("Bind...\n");
  30. servaddr.sin_family=AF_INET;
  31. servaddr.sin_port=htons(6666);
  32. servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  33. if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
  34. {
  35. printf("Bind failed.\n");
  36. return -1;
  37. }
  38. //调用listen函数,将一个主动连接套接字变为被动的倾听套接字
  39. //在此过程中完成tcp的三次握手连接
  40. printf("listening...\n");
  41. listen(listenfd,LISTENQ);
  42. //创建一个线程,对服务器程序进行管理(关闭)
  43. pthread_create(&thread,NULL,(void*)(&quit),NULL);
  44. //记录空闲的客户端的套接字描述符(-1为空闲)
  45. int i=0;
  46. for(i=0;i<MAXMEM;i++)
  47. {
  48. connfd[i]=-1;
  49. }
  50. while(1)
  51. {
  52. len=sizeof(cliaddr);
  53. for(i=0;i<MAXMEM;i++)
  54. {
  55. if(connfd[i]==-1)
  56. {
  57. break;
  58. }
  59. }
  60. //调用accept从listen接受的连接队列中取得一个连接
  61. connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
  62. ticks=time(NULL);
  63. sprintf(buff,"% .24s \r \n",ctime(&ticks));
  64. printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
  65. //针对当前套接字创建一个线程,对当前套接字的消息进行处理
  66. pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
  67. }
  68. return 0;
  69. }
  70. void quit()
  71. {
  72. char msg[10];
  73. while(1)
  74. {
  75. scanf("%s",msg);
  76. if(strcmp("quit",msg)==0)
  77. {
  78. printf("Byebye...\n");
  79. close(listenfd);
  80. exit(0);
  81. }
  82. }
  83. }
  84. void rcv_snd(int n)
  85. {
  86. char* ask="Your name please:";
  87. char buff[MAXLINE];
  88. char buff1[MAXLINE];
  89. char buff2[MAXLINE];
  90. char name[NAMELEN];
  91. time_t ticks;
  92. int i=0;
  93. int retval;
  94. //获取此进程对应的套接字用户的名字
  95. write(connfd[n],ask,strlen(ask));
  96. int len;
  97. len=read(connfd[n],name,NAMELEN);
  98. if(len>0)
  99. {
  100. name[len]=0;
  101. }
  102. //把当前用户的加入告知所有用户
  103. strcpy(buff,name);
  104. strcat(buff,"\tjoin in\0");
  105. for(i=0;i<MAXMEM;i++)
  106. {
  107. if(connfd[i]!=-1)
  108. {
  109. write(connfd[i],buff,strlen(buff));
  110. }
  111. }
  112. //接受当前用户的信息并将其转发给所有的用户
  113. while(1)
  114. {
  115. if((len=read(connfd[n],buff1,MAXLINE))>0)
  116. {
  117. buff1[len]=0;
  118. //当当前用户的输入信息为“bye”时,当前用户退出
  119. if(strcmp("bye",buff)==0)
  120. {
  121. close(connfd[n]);
  122. connfd[n]=-1;
  123. pthread_exit(&retval);
  124. }
  125. ticks=time(NULL);
  126. sprintf(buff2,"%.24s\r\n",ctime(&ticks));
#include<time.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h> #define LISTENQ 5
#define MAXLINE 512
#define MAXMEM 10
#define NAMELEN 20 int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字 void quit();//服务器关闭函数
void rcv_snd(int n);//服务器接收并转发消息函数 int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE]; //调用socket函数创建服务器端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
} //调用bind函数使得服务器端的套接字与地址实现绑定
printf("Bind...\n");
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("Bind failed.\n");
return -1;
} //调用listen函数,将一个主动连接套接字变为被动的倾听套接字
//在此过程中完成tcp的三次握手连接
printf("listening...\n");
listen(listenfd,LISTENQ); //创建一个线程,对服务器程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL); //记录空闲的客户端的套接字描述符(-1为空闲)
int i=0;
for(i=0;i<MAXMEM;i++)
{
connfd[i]=-1;
} while(1)
{
len=sizeof(cliaddr);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]==-1)
{
break;
}
} //调用accept从listen接受的连接队列中取得一个连接
connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len); ticks=time(NULL);
sprintf(buff,"% .24s \r \n",ctime(&ticks));
printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port)); //针对当前套接字创建一个线程,对当前套接字的消息进行处理
pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i); }
return 0;
} void quit()
{
char msg[10];
while(1)
{
scanf("%s",msg);
if(strcmp("quit",msg)==0)
{
printf("Byebye...\n");
close(listenfd);
exit(0);
}
}
} void rcv_snd(int n)
{
char* ask="Your name please:";
char buff[MAXLINE];
char buff1[MAXLINE];
char buff2[MAXLINE];
char name[NAMELEN];
time_t ticks;
int i=0;
int retval; //获取此进程对应的套接字用户的名字
write(connfd[n],ask,strlen(ask));
int len;
len=read(connfd[n],name,NAMELEN);
if(len>0)
{
name[len]=0;
} //把当前用户的加入告知所有用户
strcpy(buff,name);
strcat(buff,"\tjoin in\0");
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
} //接受当前用户的信息并将其转发给所有的用户
while(1)
{
if((len=read(connfd[n],buff1,MAXLINE))>0)
{
buff1[len]=0; //当当前用户的输入信息为“bye”时,当前用户退出
if(strcmp("bye",buff)==0)
{
close(connfd[n]);
connfd[n]=-1;
pthread_exit(&retval);
} ticks=time(NULL);
sprintf(buff2,"%.24s\r\n",ctime(&ticks));
  1. strcpy(buff,name);
  2. strcat(buff,"\t");
  3. strcat(buff,buff2);
  4. strcat(buff,buff1);
  5. for(i=0;i<MAXMEM;i++)
  6. {
  7. if(connfd[i]!=-1)
  8. {
  9. write(connfd[i],buff,strlen(buff));
  10. }
  11. }
  12. }
  13. }

Linux C 网络编程——多线程的聊天室实现(服务器端)的更多相关文章

  1. Linux C 网络编程——多线程的聊天室实现(server端)

    server端的主要功能: 实现多用户群体聊天功能(此程序最多设定为10人.可进行更改),每一个人所发送的消息其它用户均能够收到.用户能够任意的增加或退出(推出以字符串"bye"实 ...

  2. 网络编程TCP协议-聊天室

    网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...

  3. 使用Android网络编程实现简易聊天室

    在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP.UDP网络通信API.我们可以使用ServerSocket.Socket来建 ...

  4. 网络编程-基于Websocket聊天室(IM)系统

    目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...

  5. 嵌入式linux的网络编程(1)--TCP/IP协议概述

    嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...

  6. Linux C网络编程学习笔记

    Linux C网络编程总结报告 一.Linux C 网络编程知识介绍: 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端:(client) 在网络程序中, ...

  7. Linux C++ 网络编程学习系列(1)——端口复用实现

    Linux C++ 网络编程学习系列(1)--端口复用实现 源码地址:https://github.com/whuwzp/linuxc/tree/master/portreuse 源码说明: serv ...

  8. Linux&C网络编程————“聊天室”

    从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...

  9. Linux&C网络编程————“聊天室”

    从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...

随机推荐

  1. 沙漏集合 good

    曾经的高考状元,如今都过得怎么样呢?http://www.toutiao.com/a6428794132465975554/ 你可知道,古代女人为什么不能当官——笑昏我了http://tieba.ba ...

  2. U盘免疫

    界面如下: 关键部分代码如下: void CImmunityUDlg::OnBnClickedButtonOk() { // TODO: 在此添加控件通知处理程序代码 TCHAR szPath[MAX ...

  3. 搭建RPC over HTTP 环境遇到的问题

    最近需要做RPC的IPS协议分析,需要了解一下RPC over HTTP的协议格式,由于此类数据包不易构造,故此想搭建一个抓一些包分析一下. 结果搭建这么个环境硬是用了我四个工作日的时间,崩溃加无语. ...

  4. javaweb各种框架组合案例(二):maven+spring+springMVC+mybatis

    1.mybatis是比较新的半自动orm框架,效率也比较高,优点是sql语句的定制,管理与维护,包括优化,缺点是对开发人员的sql功底要求较高,如果比较复杂的查询,表与表之间的关系映射到对象与对象之间 ...

  5. 3013C语言_输入输出

    第三章 输入输出 3.1输入输出概念及其实现 (1)数据从计算机内部向外部输出设备(如显示器.打印机等)输送的操作称为 “输出”,数据从计算机外部向输入设备(如键盘.鼠标.扫描仪等)送入的操作称为 “ ...

  6. Servlet 3.0异步特性初探

    Servlet 是 Java 为了编写服务端程序而定义的一个接口规范,在 Servlet 3.0 以后支持了异步的操作. 最近项目添加了一个代码热部署的功能,在客户端输入信号,信号到达 Web 服务器 ...

  7. 解决wireshark打开错误

    错误提示如下: Lua: Error during loading: [string "/usr/share/wireshark/init.lua"]:44: dofile has ...

  8. Flink UDF

    本文会主要讲三种udf: ScalarFunction TableFunction AggregateFunction 用户自定义函数是非常重要的一个特征,因为他极大地扩展了查询的表达能力.本文除了介 ...

  9. Python批量自动裁剪图片

    """用Pythonp批量裁剪图片""" from PIL import Image import matplotlib.pyplot as ...

  10. Linux文件系统目录结构详解

    在我们初学嵌入式Linux时,首先学习的就是Linux的最小根文件系统:下面我将为初学者们详细的阐述一下Linux的最小根文件系统. 根目录在Linux中即为“/”,要进入根目录,命令“cd  /”即 ...