1. #include<string.h>
  2. #include<signal.h>
  3. #include<stdio.h>
  4. #include<sys/socket.h>
  5. #include<stdlib.h>
  6. #include<netdb.h>
  7. #include<pthread.h>
  8. #include<memory.h>
  9. #include<semaphore.h>
  10. int Thread_num=,count=; //定义客户端计数器,写线程计数器
  11. int sockfd;
  12. sem_t sem,sem2;
  13. pthread_mutex_t tmutex,cmutex;
  14. pthread_attr_t pattr; //定义要创建的线程属性
  15. void ct_thread(char* arg,int acpfd);
  16. char chatct[]; //定义聊天缓存
  17. void get_sys_time(char* tbuf) //函数功能:得到当前系统时间并进行裁剪
  18. {
  19. long t=time();
  20. char *stime=ctime(&t);
  21. int i=;
  22. tbuf[]='(';
  23. for(;i<;i++)
  24. tbuf[i-]=stime[i];
  25. tbuf[i-]=')';
  26. tbuf[i-]='\0';
  27. }
  28. void* do_read(void* arg) //函数功能:读线程,用于接收客户端发来的信息,保存到缓冲区
    {
  29. int acfd=(int)arg;
  30. char timeb[];
  31. // char name[7];
  32. // memset(name,0,sizeof(name));
  33. // read(acfd,name,sizeof(name));
  34. // name[sizeof(name)-1]='\0';
  35. // puts(name);
  36. while()
  37. {
  38. int ret;
  39. char buf[];
  40. memset(buf,,sizeof(buf));
  41. ret=read(acfd,buf,sizeof(buf));
  42. sem_wait(&sem2);
  43. if(ret<)
  44. {
  45. perror("do_read errro");
  46. continue;
  47. }
  48. else if(ret==)
  49. {
  50. close(acfd);
  51. sem_post(&sem2);
  52. printf("a person exit\n");
  53. break;
  54. }
  55. else
  56. {
  57. memset(timeb,,sizeof(timeb));
  58. // strcpy(chatct,name);
  59. // puts(chatct);
  60. // strcat(chatct,":");
  61. // puts(chatct);
  62. get_sys_time(timeb);
  63. strcpy(chatct,buf);
  64. strcat(chatct,timeb);
  65. // puts(chatct);
  66. // printf("do_read %lu\n",pthread_self());
  67. sem_post(&sem);
  68. }
  69. // puts(chatct);
  70. }
  71. return (void*);
  72. }
  73. void* do_write(void* arg) //函数功能:写线程,用于将缓冲区的数据发送到连接上来的每个客户端,当所有客户端接收到消息后,清空缓冲区。
  74. {
  75. int fd=(int)arg;
  76. while()
  77. {
  78. sem_wait(&sem);
  79. if(write(fd,chatct,sizeof(chatct))<)
  80. {
  81. Thread_num--;
  82. if(count==Thread_num)
  83. {
  84. memset(chatct,,sizeof(chatct));
  85. pthread_mutex_lock(&cmutex);
  86. count=;
  87. pthread_mutex_unlock(&cmutex);
  88. sem_post(&sem2);
  89.  
  90. }
  91. else if(count<Thread_num)
  92. {
  93. sem_post(&sem);
  94. }
  95. close(fd);
  96. break;
  97. }
  98. else
  99. {
  100. pthread_mutex_lock(&cmutex);
  101. count++;
  102. pthread_mutex_unlock(&cmutex);
  103. }
  104. if(count<Thread_num)
  105. {
  106. sem_post(&sem);
  107. usleep();
  108. }
  109. else if(count==Thread_num)
  110. {
  111. memset(chatct,,sizeof(chatct));
  112. pthread_mutex_lock(&cmutex);
  113. count=;
  114. pthread_mutex_unlock(&cmutex);
  115. sem_post(&sem2);
  116. }
  117. }
  118. return (void*);
  119. }
  120. void do_thread(int acpfd) //函数功能:对于每个连接上来的客户端 创建一个读线程,一个写线程
  121. {
  122. // char* start="------------------welcome my chatroom--------------------\n";
  123. // write(acpfd,start,strlen(start));
  124. pthread_mutex_lock(&cmutex);
  125. Thread_num++; //每创建一个 线程个数计数加1
  126. pthread_mutex_unlock(&cmutex);
  127. ct_thread("read",acpfd);
  128. ct_thread("write",acpfd);
  129. }
  130. void ct_thread(char* arg,int acpfd) //函数功能,根据传参不同,创建不同类型的函数。
  131. {
  132. pthread_t pt;
  133. /* if(!strcmp(arg,"create"))
  134. {
  135. if(pthread_create(&pt,&pattr,thread_ct,(void*)acpfd)<0)
  136. {
  137. perror("thread creat error");
  138. exit(1);
  139. }
  140. }
  141. */ //以分离方式创建线程可避免资源无法回收
  142. if(!strcmp(arg,"read"))
  143. {
  144. if(pthread_create(&pt,&pattr,do_read,(void*)acpfd)<)
  145. {
  146. perror("thread creat error");
  147. exit();
  148. }
  149. }
  150. else if(!strcmp(arg,"write"))
  151. {
  152. if(pthread_create(&pt,&pattr,do_write,(void*)acpfd)<)
  153. {
  154. perror("thread creat error");
  155. exit();
  156. }
  157. }
  158. }
  159. void mysighand(int signo) //函数功能:当程序结束,处理返回的信号,释放资源
  160. {
  161. if(signo==SIGINT)
  162. {
  163. printf("server close!\n");
  164. close(sockfd);
  165. sem_destroy(&sem);
  166. sem_destroy(&sem2);
  167. pthread_mutex_destroy(&cmutex);
  168. pthread_mutex_destroy(&tmutex);
  169. pthread_attr_destroy(&pattr);
  170. exit();
  171. }
  172. }
  173. int main(int argc,char* argv[])
  174. {
  175. if(argc<)
  176. {
  177. perror("argc error");
  178. exit();
  179. }
  180. if(signal(SIGINT,mysighand)==SIG_ERR) //登记信号处理函数
  181. {
  182. perror("signal error");
  183. exit();
  184. }
    /* 1 初始化
  185. sem_init(&sem,,);
  186. sem_init(&sem2,,);
  187. pthread_mutex_init(&tmutex,NULL);
  188. pthread_mutex_init(&cmutex,NULL);
  189. pthread_attr_init(&pattr);
    */
      if(pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED)<) //设置分离属性
  190. {
  191. perror("setdetached error");
  192. exit();
  193. }
  194. memset(chatct,,sizeof(chatct)); //初始化缓存区
  195. sockfd=socket(AF_INET,SOCK_STREAM,);//以TCP方式创建socket
  196. if(sockfd<)
  197. {
  198. perror("sockfd error");
  199. exit();
  200. }
  201. struct sockaddr_in ser;
  202. ser.sin_family=AF_INET;        //IP类型:IPV4
  203. ser.sin_port=htons(atoi(argv[])); //主机字节序转换成网络字节序
  204. ser.sin_addr.s_addr=INADDR_ANY;  //主机所有可访问IP 
  205. if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser))<) //socket和IP绑定
  206. {
  207. perror("bind error");
  208. exit();
  209. }
  210. if(listen(sockfd,)<) //进行监听等待客户端连接
  211. {
  212. perror("listen error");
  213. exit();
  214. }
  215. while()
  216. {
  217. int acpfd;
  218. if((acpfd=accept(sockfd,NULL,NULL))<) //处理每个连接上来的客户端,如果无客户端连接,则阻塞
  219. break;
  220. else
  221. {
  222. do_thread(acpfd); //执行处理连接函数
  223. }
  224. }
  225. return ;
  226. }

本服务端的主要思想:

为每一个连接上来的客户端创建一个读线程和写线程(分离状态启动的线程,线程进行自我资源回收),服务端和客户端的通信实际就是多读者多写者的模型(利用信号量和客户端计数器,线程计数器,实现线程的同步和互斥)

不同点在于 当客户端断开连接后,服务端应当及时改变客户端计数器,并进行逻辑处理。

服务端运行在云服务器上,客户端可以用QT 或者android 等来实现。

不足点:

仅仅是匿名聊天。功能较简单。只是显示聊天内容和数据发送的时间

优点:

可以支持大量客户端同时进行连接。并且在网络速度不健康的情况下数据不会出错(非网络在信道传递时的错误)

  1.  

socket聊天室(服务端)(多线程)(TCP)的更多相关文章

  1. Socket聊天程序——服务端

    写在前面: 昨天在博客记录自己抽空写的一个Socket聊天程序的初始设计,那是这个程序的整体设计,为了完整性,今天把服务端的设计细化记录一下,首页贴出Socket聊天程序的服务端大体设计图,如下图: ...

  2. Winfrom 基于TCP的Socket服务端 多线程(进阶版)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  3. 用c++语言socket库函数实现服务端客户端聊天室

    客户端 /* * 程序名:client.cpp,此程序用于演示socket的客户端 * 作者:C语言技术网(www.freecplus.net) 日期:20190525 */ #include < ...

  4. TCP/IP以及Socket聊天室带类库源码分享

    TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...

  5. Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

    这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...

  6. python socket 聊天室

    socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...

  7. Asp.Net - 9.socket(聊天室)

    9.1 Socket相关概念 IP地址 每台联网的电脑都有一个唯一的IP地址. 长度32位,分为四段,每段8位,用十进制数字表示,每段范围 0 ~ 255 特殊IP:127.0.0.1 用户本地网卡测 ...

  8. Java Socket聊天室编程(二)之利用socket实现单聊聊天室

    这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...

  9. Socket通信时服务端无响应,客户端超时设置

    背景:在写一个客户端的socket程序,服务端没有返回消息,客户端一直在等待. 目标:我需要设置一个时间,如果超过这个时间客户端自动断开连接.最好是在服务端实现,客户端对我来说不可控.

随机推荐

  1. angular购物车

    <body ng-app> <div class="container" ng-controller="carController"> ...

  2. 为什么大多数培训机构还停留在只教ssh框架?

    最近听一些朋友说,招聘面试的很多人简历都差不多,大部分人的简历上面都写了熟悉ssh框架,我朋友就在吐槽,为什么这些人简历都差不多,并且都熟悉ssh框架? 后面他说, 可能这些人都是培训机构出来的, 然 ...

  3. 开通阿里云 CDN

    CDN,内容分发网络,主要功能是在不同的地点缓存内容,通过负载均衡技术,将用户的请求定向到最合适的缓存服务器上去获取内容,从而加快文件加载速度. 阿里云提供了按量计费的CDN,开启十分方便,于是我在自 ...

  4. Javascript中Array(数组)对象常用的几个方法

    Javascript中Array数组的几个常用方法 pop()  --获取数组中末尾的元素 shift() --获取数组中首位元素 push() --在数组中末尾增加元素 slice()  --按照下 ...

  5. 分布式文件系统:HDFS

    学习Hadoop,两个东西肯定是绕不过,MapReduce和HDFS,上一篇博客介绍了MapReduce的处理流程,这一篇博客就来学习一下HDFS. HDFS是一个分布式的文件系统,就是将多台机器的存 ...

  6. 直方图均衡化CImg实现

    这篇博客是关于试用CImg库来实现灰度图和彩色图的直方图均衡化操作.感觉效果还不错,除了彩色图在均衡化时会有一定的色彩失真. C++代码实现: // // hEqualization.hpp // 直 ...

  7. 深入浅出node.js

    http://www.infoq.com/cn/articles/what-is-nodejs/

  8. 微信小程序框架

    框架 小程序开发框架的目标是通过尽可能简单.高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务. 框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的 ...

  9. shop_list

    #!/usr/bin/env python # -*- coding: utf-8 -*- #输出商品列表,用户输入序号,显示用户选中的商品 li = ["手机", "电 ...

  10. 利用GROUP_CONCAT和GROUP BY实现字段拼接

    在开发过程中遇到这样的一个需求,通过GROUP BY分组归类后将同属性的字段进行拼接. 表结构为: id value a b c a b 需要得到结果: id value a,b,c a,b 一开始在 ...