服务器端的主要功能:

实现多用户群体聊天功能(此程序最多设定为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. 我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 Internet 上用于确保您通信的安全性。

    早上使用.Net WebClient类采集亚马逊数据,返回http 400 Bad Request错误,内容里面有“我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 ...

  2. Qt for Android之Hello World

    Qt for Android (Hello World APK 创建)Qt是跨平台的,如桌面.移动.嵌入式平台.Qt for Android可以在Android v2.3.3 (API level 1 ...

  3. XPath概述

    1.  XPath 具体示例可参考网址: http://www.zvon.org/xxl/XPathTutorial/General/examples.html 1.1 概述 * 现节点下所有元素 * ...

  4. Codility---Nesting

    Task description A string S consisting of N characters is called properly nested if: S is empty; S h ...

  5. 似乎是VS2017的一个BUG

    VS版本:2017(15.9.13) 新建一个c#控制台项目,把Program.cs的内容替换成如下: namespace ConsoleApp1 { class Program { static v ...

  6. java.lang.ClassNotFoundException: org.hibernate.ejb.HibernatePersistence 解决方法

    编译遇到错误,如下: May 11, 2017 1:49:42 PM org.springframework.web.context.ContextLoader initWebApplicationC ...

  7. ZooKeeper学习第八期——ZooKeeper伸缩性(转)

    转载来源:https://www.cnblogs.com/sunddenly/p/4143306.html 一.ZooKeeper中Observer 1.1 ZooKeeper角色 经过前面的介绍,我 ...

  8. Java打印实心、空心的三角形和菱形

    1.实心三角形 代码: import java.util.Scanner; public class Test { public static void main(String[] args) { i ...

  9. 【JVM】01虚拟机内存模型

    学习链接:https://blog.csdn.net/u010425776/article/details/51170118 博主整理的条理清晰,在这里先感谢博主分享 去年看视频学习写过一篇JVM的博 ...

  10. Python开发【第七篇】: 面向对象和模块补充

    内容概要 特殊成员 反射 configparser模块 hashlib模块 logging模块 异常处理 模块 包 1. 特殊成员 什么是特殊成员呢? __init_()就是个特殊的成员. 带双下划线 ...