socket聊天室(服务端)(多线程)(TCP)
- #include<string.h>
- #include<signal.h>
- #include<stdio.h>
- #include<sys/socket.h>
- #include<stdlib.h>
- #include<netdb.h>
- #include<pthread.h>
- #include<memory.h>
- #include<semaphore.h>
- int Thread_num=,count=; //定义客户端计数器,写线程计数器
- int sockfd;
- sem_t sem,sem2;
- pthread_mutex_t tmutex,cmutex;
- pthread_attr_t pattr; //定义要创建的线程属性
- void ct_thread(char* arg,int acpfd);
- char chatct[]; //定义聊天缓存
- void get_sys_time(char* tbuf) //函数功能:得到当前系统时间并进行裁剪
- {
- long t=time();
- char *stime=ctime(&t);
- int i=;
- tbuf[]='(';
- for(;i<;i++)
- tbuf[i-]=stime[i];
- tbuf[i-]=')';
- tbuf[i-]='\0';
- }
- void* do_read(void* arg) //函数功能:读线程,用于接收客户端发来的信息,保存到缓冲区
{- int acfd=(int)arg;
- char timeb[];
- // char name[7];
- // memset(name,0,sizeof(name));
- // read(acfd,name,sizeof(name));
- // name[sizeof(name)-1]='\0';
- // puts(name);
- while()
- {
- int ret;
- char buf[];
- memset(buf,,sizeof(buf));
- ret=read(acfd,buf,sizeof(buf));
- sem_wait(&sem2);
- if(ret<)
- {
- perror("do_read errro");
- continue;
- }
- else if(ret==)
- {
- close(acfd);
- sem_post(&sem2);
- printf("a person exit\n");
- break;
- }
- else
- {
- memset(timeb,,sizeof(timeb));
- // strcpy(chatct,name);
- // puts(chatct);
- // strcat(chatct,":");
- // puts(chatct);
- get_sys_time(timeb);
- strcpy(chatct,buf);
- strcat(chatct,timeb);
- // puts(chatct);
- // printf("do_read %lu\n",pthread_self());
- sem_post(&sem);
- }
- // puts(chatct);
- }
- return (void*);
- }
- void* do_write(void* arg) //函数功能:写线程,用于将缓冲区的数据发送到连接上来的每个客户端,当所有客户端接收到消息后,清空缓冲区。
- {
- int fd=(int)arg;
- while()
- {
- sem_wait(&sem);
- if(write(fd,chatct,sizeof(chatct))<)
- {
- Thread_num--;
- if(count==Thread_num)
- {
- memset(chatct,,sizeof(chatct));
- pthread_mutex_lock(&cmutex);
- count=;
- pthread_mutex_unlock(&cmutex);
- sem_post(&sem2);
- }
- else if(count<Thread_num)
- {
- sem_post(&sem);
- }
- close(fd);
- break;
- }
- else
- {
- pthread_mutex_lock(&cmutex);
- count++;
- pthread_mutex_unlock(&cmutex);
- }
- if(count<Thread_num)
- {
- sem_post(&sem);
- usleep();
- }
- else if(count==Thread_num)
- {
- memset(chatct,,sizeof(chatct));
- pthread_mutex_lock(&cmutex);
- count=;
- pthread_mutex_unlock(&cmutex);
- sem_post(&sem2);
- }
- }
- return (void*);
- }
- void do_thread(int acpfd) //函数功能:对于每个连接上来的客户端 创建一个读线程,一个写线程
- {
- // char* start="------------------welcome my chatroom--------------------\n";
- // write(acpfd,start,strlen(start));
- pthread_mutex_lock(&cmutex);
- Thread_num++; //每创建一个 线程个数计数加1
- pthread_mutex_unlock(&cmutex);
- ct_thread("read",acpfd);
- ct_thread("write",acpfd);
- }
- void ct_thread(char* arg,int acpfd) //函数功能,根据传参不同,创建不同类型的函数。
- {
- pthread_t pt;
- /* if(!strcmp(arg,"create"))
- {
- if(pthread_create(&pt,&pattr,thread_ct,(void*)acpfd)<0)
- {
- perror("thread creat error");
- exit(1);
- }
- }
- */ //以分离方式创建线程可避免资源无法回收
- if(!strcmp(arg,"read"))
- {
- if(pthread_create(&pt,&pattr,do_read,(void*)acpfd)<)
- {
- perror("thread creat error");
- exit();
- }
- }
- else if(!strcmp(arg,"write"))
- {
- if(pthread_create(&pt,&pattr,do_write,(void*)acpfd)<)
- {
- perror("thread creat error");
- exit();
- }
- }
- }
- void mysighand(int signo) //函数功能:当程序结束,处理返回的信号,释放资源
- {
- if(signo==SIGINT)
- {
- printf("server close!\n");
- close(sockfd);
- sem_destroy(&sem);
- sem_destroy(&sem2);
- pthread_mutex_destroy(&cmutex);
- pthread_mutex_destroy(&tmutex);
- pthread_attr_destroy(&pattr);
- exit();
- }
- }
- int main(int argc,char* argv[])
- {
- if(argc<)
- {
- perror("argc error");
- exit();
- }
- if(signal(SIGINT,mysighand)==SIG_ERR) //登记信号处理函数
- {
- perror("signal error");
- exit();
- }
/* 1 初始化- sem_init(&sem,,);
- sem_init(&sem2,,);
- pthread_mutex_init(&tmutex,NULL);
- pthread_mutex_init(&cmutex,NULL);
- pthread_attr_init(&pattr);
*/
if(pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED)<) //设置分离属性- {
- perror("setdetached error");
- exit();
- }
- memset(chatct,,sizeof(chatct)); //初始化缓存区
- sockfd=socket(AF_INET,SOCK_STREAM,);//以TCP方式创建socket
- if(sockfd<)
- {
- perror("sockfd error");
- exit();
- }
- struct sockaddr_in ser;
- ser.sin_family=AF_INET; //IP类型:IPV4
- ser.sin_port=htons(atoi(argv[])); //主机字节序转换成网络字节序
- ser.sin_addr.s_addr=INADDR_ANY; //主机所有可访问IP
- if(bind(sockfd,(struct sockaddr*)&ser,sizeof(ser))<) //socket和IP绑定
- {
- perror("bind error");
- exit();
- }
- if(listen(sockfd,)<) //进行监听等待客户端连接
- {
- perror("listen error");
- exit();
- }
- while()
- {
- int acpfd;
- if((acpfd=accept(sockfd,NULL,NULL))<) //处理每个连接上来的客户端,如果无客户端连接,则阻塞
- break;
- else
- {
- do_thread(acpfd); //执行处理连接函数
- }
- }
- return ;
- }
本服务端的主要思想:
为每一个连接上来的客户端创建一个读线程和写线程(分离状态启动的线程,线程进行自我资源回收),服务端和客户端的通信实际就是多读者多写者的模型(利用信号量和客户端计数器,线程计数器,实现线程的同步和互斥)
不同点在于 当客户端断开连接后,服务端应当及时改变客户端计数器,并进行逻辑处理。
服务端运行在云服务器上,客户端可以用QT 或者android 等来实现。
不足点:
仅仅是匿名聊天。功能较简单。只是显示聊天内容和数据发送的时间
优点:
可以支持大量客户端同时进行连接。并且在网络速度不健康的情况下数据不会出错(非网络在信道传递时的错误)
socket聊天室(服务端)(多线程)(TCP)的更多相关文章
- Socket聊天程序——服务端
写在前面: 昨天在博客记录自己抽空写的一个Socket聊天程序的初始设计,那是这个程序的整体设计,为了完整性,今天把服务端的设计细化记录一下,首页贴出Socket聊天程序的服务端大体设计图,如下图: ...
- Winfrom 基于TCP的Socket服务端 多线程(进阶版)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 用c++语言socket库函数实现服务端客户端聊天室
客户端 /* * 程序名:client.cpp,此程序用于演示socket的客户端 * 作者:C语言技术网(www.freecplus.net) 日期:20190525 */ #include < ...
- TCP/IP以及Socket聊天室带类库源码分享
TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...
- Java Socket聊天室编程(一)之利用socket实现聊天之消息推送
这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...
- python socket 聊天室
socket 发送的时候,使用的是全双工的形式,不是半双工的形式.全双工就是类似于电话,可以一直通信.并且,在发送后,如果又接受数据,那么在这个接受到数据之前,整个过程是不会停止的.会进行堵塞,堵塞就 ...
- Asp.Net - 9.socket(聊天室)
9.1 Socket相关概念 IP地址 每台联网的电脑都有一个唯一的IP地址. 长度32位,分为四段,每段8位,用十进制数字表示,每段范围 0 ~ 255 特殊IP:127.0.0.1 用户本地网卡测 ...
- Java Socket聊天室编程(二)之利用socket实现单聊聊天室
这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...
- Socket通信时服务端无响应,客户端超时设置
背景:在写一个客户端的socket程序,服务端没有返回消息,客户端一直在等待. 目标:我需要设置一个时间,如果超过这个时间客户端自动断开连接.最好是在服务端实现,客户端对我来说不可控.
随机推荐
- angular购物车
<body ng-app> <div class="container" ng-controller="carController"> ...
- 为什么大多数培训机构还停留在只教ssh框架?
最近听一些朋友说,招聘面试的很多人简历都差不多,大部分人的简历上面都写了熟悉ssh框架,我朋友就在吐槽,为什么这些人简历都差不多,并且都熟悉ssh框架? 后面他说, 可能这些人都是培训机构出来的, 然 ...
- 开通阿里云 CDN
CDN,内容分发网络,主要功能是在不同的地点缓存内容,通过负载均衡技术,将用户的请求定向到最合适的缓存服务器上去获取内容,从而加快文件加载速度. 阿里云提供了按量计费的CDN,开启十分方便,于是我在自 ...
- Javascript中Array(数组)对象常用的几个方法
Javascript中Array数组的几个常用方法 pop() --获取数组中末尾的元素 shift() --获取数组中首位元素 push() --在数组中末尾增加元素 slice() --按照下 ...
- 分布式文件系统:HDFS
学习Hadoop,两个东西肯定是绕不过,MapReduce和HDFS,上一篇博客介绍了MapReduce的处理流程,这一篇博客就来学习一下HDFS. HDFS是一个分布式的文件系统,就是将多台机器的存 ...
- 直方图均衡化CImg实现
这篇博客是关于试用CImg库来实现灰度图和彩色图的直方图均衡化操作.感觉效果还不错,除了彩色图在均衡化时会有一定的色彩失真. C++代码实现: // // hEqualization.hpp // 直 ...
- 深入浅出node.js
http://www.infoq.com/cn/articles/what-is-nodejs/
- 微信小程序框架
框架 小程序开发框架的目标是通过尽可能简单.高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务. 框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的 ...
- shop_list
#!/usr/bin/env python # -*- coding: utf-8 -*- #输出商品列表,用户输入序号,显示用户选中的商品 li = ["手机", "电 ...
- 利用GROUP_CONCAT和GROUP BY实现字段拼接
在开发过程中遇到这样的一个需求,通过GROUP BY分组归类后将同属性的字段进行拼接. 表结构为: id value a b c a b 需要得到结果: id value a,b,c a,b 一开始在 ...