[转载]socket下server端支持多客户端并发访问简单实现
/*Author: wainiwann
*Source: 博客园 http://www.cnblogs.com/wainiwann
*Remarks: 转载请说明出处!!!
*/
感觉很不错,可以学习一下。
socket下server端支持多客户端并发访问简单实现
server端开启之后始终有两个线程在处理连接请求,一个是只负责客户端的请求连接的(这里是只针对TCP协议),当客户端connect的时候 记录当前客户端连接存放到数据组中当中,而这个数组声明为全局成员,其实在线程内处理外部成员的话,也没必要非要用静态或者全局成员,今天听经理说也可以 在创建该线程时,把某类的this指针传递过去,同样好像也可以访问public成员的,具体行不行,还没试不过真的是不错的方法。要知道很多在项目很避 讳使用全局的东西,甚至有的公司直接不让使用全局的东西。这里扯的有点远了。
另外一个同步允许的线程就是对accept记录的数组进行操作,依次处理各个客户端请求通信和状态监控等,当数组内socket成员不为空时记录当前索引然后在create发送或者获取线程处理函数并发响应多个客户端的连接请求通信
加载套接字库:
BOOL TcpServer::InitSocket()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( , );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != )
{
return FALSE;
} if ( LOBYTE( wsaData.wVersion ) != || HIBYTE( wsaData.wVersion ) != )
{
WSACleanup( );
return FALSE;
} //创建套接字
//SOCKET m_socket=socket(AF_INET,SOCK_STREAM,0); return TRUE;
}
开启执行Accept线程处理函数:
BOOL TcpServer::SatartServer()
{
//创建线程
HANDLE hThread = CreateThread(NULL,,ThreadProc_Accept,NULL,,NULL);
//关闭该接收线程句柄,释放引用计数
CloseHandle(hThread); return TRUE;
}
线程处理函数:
DWORD WINAPI TcpServer::ThreadProc_Accept(LPVOID lpParameter)
{
int len = sizeof(SOCKADDR);
int err;
m_socket=socket(AF_INET,SOCK_STREAM,);
if (m_socket == INVALID_SOCKET)
{
AfxMessageBox(_T("套接字创建失败!"));
return FALSE;
} SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(); err = bind(m_socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定本地端口
if (err==SOCKET_ERROR)
{
closesocket(m_socket);
AfxMessageBox(_T("绑定失败!"));
return FALSE;
}
listen(m_socket,);//开启监听 //创建线程
HANDLE hThread = CreateThread(NULL,,ThreadProc_Select,NULL,,NULL);
//关闭该接收线程句柄,释放引用计数
CloseHandle(hThread); while (TRUE)
{
m_CliSocketArr[m_ToolConn++] = accept(m_socket,(SOCKADDR*)&addrSrv,&len);
}
return ;
}
同时在该线程函数内创建处理客户端数组的线程处理函数:
DWORD WINAPI TcpServer::ThreadProc_Select(LPVOID lpParameter)
{
int recvflag=; fd_set fdread; //读集fdread
int ret; //查看某个套接字的状态
struct timeval tv = {,}; //实例化timeval变量 while (TRUE)
{
//判断当前连接数是否为 0
if (m_ToolConn == )
{
Sleep();
continue;
} FD_ZERO(&fdread);
for (int i = ;i < m_ToolConn;i++)
{
FD_SET(m_CliSocketArr[i],&fdread);
}
ret = select(,&fdread,NULL,NULL,&tv);
if (ret == )
{
continue;
}
for (int i =;i<m_ToolConn;i++)
{
if (FD_ISSET(m_CliSocketArr[i],&fdread))
{
ret = recv(m_CliSocketArr[i],(char*)&recvflag,sizeof(int)+,);
if (ret == || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
closesocket(m_CliSocketArr[i]);
if (i < m_ToolConn-)
{
m_CliSocketArr[i] = m_CliSocketArr[--m_ToolConn];
}else
{
--m_ToolConn;
} }else
{
INDEX * inx = new INDEX;
inx->flag = recvflag;
inx->index = i; //创建线程
HANDLE hThread = CreateThread(NULL,,ThreadProc_Response,(LPVOID)inx,,NULL);
//关闭该接收线程句柄,释放引用计数
CloseHandle(hThread); }
}//if
}//for
}//while return ;
}
下面就是一次创建线程并发处理客户端请求线程处理函数:
DWORD WINAPI TcpServer::ThreadProc_Response(LPVOID lpParameter)
{
int ix = ((INDEX*)lpParameter)->index;
int flag = ((INDEX*)lpParameter)->flag; delete lpParameter; if (flag == )
{
//.............................
unsigned char sendBuffer[] = {'a'};
send(m_CliSocketArr[ix],(char*)sendBuffer,sizeof(sendBuffer)+,);
} return ;
}
线程处理函数在定义时,要设置为static或者是全局函数。
[转载]socket下server端支持多客户端并发访问简单实现的更多相关文章
- 在socket的server端处理client端发来的数据
一.楔子 最近做了一个需求遇到一个坑,归结成一个小问题,其实就是在socket的server端处理client端发来的数据的问题,现将这个问题总结一下,本文将数据在server端以字典的形式存储. 另 ...
- Linux下的C Socket编程 -- server端的简单示例
Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
- [转载]linux下配置mariadb支持中文
转载网址:http://www.cnblogs.com/vingi/articles/4302330.html 修改/etc/mysql/my.cnfOn MySQL 5.5 I have in my ...
- 上机题目(0基础)- Java网络操作-Socket实现client和server端通信二(Java)
上一节实现了client像server端发送请求.本节将实现server端向client回传信息.实现原理非常easy,在原来的基础上.在server端实现输出流,在client实现输入流就可以,详细 ...
- 从零开始学习Node.js例子四 多页面实现数学运算 续二(client端和server端)
1.server端 支持数学运算的服务器,服务器的返回结果用json对象表示. math-server.js //通过监听3000端口使其作为Math Wizard的后台程序 var math = r ...
- 一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断?
我们有2台内部http服务(nginx): 201:这台服务器部署的服务是account.api.91160.com,这个服务是供前端页面调用: 202:这台服务器部署的服务是hdbs.api.911 ...
- [转载] Linux下高并发socket最大连接数所受的各种限制
原文: http://mp.weixin.qq.com/s?__biz=MzAwNjMxNjQzNA==&mid=207772333&idx=1&sn=cfc8aadb422f ...
- java socket实现服务端,客户端简单网络通信。Chat
之前写的实现简单网络通信的代码,有一些严重bug.后面详细写. 根据上次的代码,主要增加了用户注册,登录页面,以及实现了实时显示当前在登录状态的人数.并解决一些上次未发现的bug.(主要功能代码参见之 ...
随机推荐
- C++中的单例模式
单例模式也称为单件模式.单子模式,可能是使用最广泛的设计模式.其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享.有很多地方需要这样的功能模块,如系统的日志输出,G ...
- Linux磁盘空间被未知资源耗尽【转】
Linux磁盘空间被未知资源耗尽 在linux中,当我们使用rm在linux上删除了大文件,但是如果有进程打开了这个大文件,却没有关闭这个文件的句柄,那么linux内核还是不会释放这个文件的磁盘空间, ...
- 如何在python3.3用 map filter reduce
在3.3里,如果直接使用map(), filter(), reduce(), 会出现 >>> def f(x): return x % 2 != 0 and x % 3 != 0 ...
- lucene 基本原理整理
基本原理:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623594.html 所有过程:http://www.cnblogs.co ...
- understanding checkpoint_completion_target
Starting new blog series – explanation of various configuration parameters. I will of course follow ...
- Linux进程间通信-匿名管道
前面我们讲了进程间通信的一种方式,共享内存.下面看一看另一种机制,匿名管道.1.什么是管道管道是一个进程的数据流到另一个进程的通道,即一个进程的数据输出作为另一个进程的数据输入,管道起到了桥梁的作用. ...
- OpenJudge就算概论-最长单词2【寻找句子内部最长的单词】
/*===================================== 最长单词2 总时间限制: 1000ms 内存限制: 65536kB 描述 一个以'.'结尾的简单英文句子,单词之间用空格 ...
- nginx https http 共用
openssl genrsa -des3 -out banmaxiaozhen.com.key 1024 openssl req -new -key banmaxiaozhen.com.key -ou ...
- XMLHttpRequest 对象
XMLHttpRequest 对象 XML XSLTXML 解析器XMLHttpRequest 对象用于在后台与服务器交换数据. 什么是 XMLHttpRequest 对象? XMLHttpReque ...
- html之dl标签
用来定义列表之用 通常与dt:定义列表中的项目 dd:描述列表中的项目 示例代码: <dl> <dt>数据库</dt> <dd>oracle</d ...