/*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端支持多客户端并发访问简单实现的更多相关文章

  1. 在socket的server端处理client端发来的数据

    一.楔子 最近做了一个需求遇到一个坑,归结成一个小问题,其实就是在socket的server端处理client端发来的数据的问题,现将这个问题总结一下,本文将数据在server端以字典的形式存储. 另 ...

  2. Linux下的C Socket编程 -- server端的简单示例

    Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...

  3. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  4. [转载]linux下配置mariadb支持中文

    转载网址:http://www.cnblogs.com/vingi/articles/4302330.html 修改/etc/mysql/my.cnfOn MySQL 5.5 I have in my ...

  5. 上机题目(0基础)- Java网络操作-Socket实现client和server端通信二(Java)

    上一节实现了client像server端发送请求.本节将实现server端向client回传信息.实现原理非常easy,在原来的基础上.在server端实现输出流,在client实现输入流就可以,详细 ...

  6. 从零开始学习Node.js例子四 多页面实现数学运算 续二(client端和server端)

    1.server端 支持数学运算的服务器,服务器的返回结果用json对象表示. math-server.js //通过监听3000端口使其作为Math Wizard的后台程序 var math = r ...

  7. 一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断?

    我们有2台内部http服务(nginx): 201:这台服务器部署的服务是account.api.91160.com,这个服务是供前端页面调用: 202:这台服务器部署的服务是hdbs.api.911 ...

  8. [转载] Linux下高并发socket最大连接数所受的各种限制

    原文: http://mp.weixin.qq.com/s?__biz=MzAwNjMxNjQzNA==&mid=207772333&idx=1&sn=cfc8aadb422f ...

  9. java socket实现服务端,客户端简单网络通信。Chat

    之前写的实现简单网络通信的代码,有一些严重bug.后面详细写. 根据上次的代码,主要增加了用户注册,登录页面,以及实现了实时显示当前在登录状态的人数.并解决一些上次未发现的bug.(主要功能代码参见之 ...

随机推荐

  1. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  2. 看完com本质论第一章

    class IUnKnown { virtual void QueryInterface(REFIID riid,IUnknown** ppv)=0; virtual void addref()=0; ...

  3. google-perftools 分析JAVA 堆外内存

    google-perftools 分析JAVA 堆外内存 分类: j2se2011-08-25 21:48 3358人阅读 评论(4) 收藏 举报 javahbasehtml工具os 原文转自:htt ...

  4. CSS中:display:none与visible:hidden的区别

    display:none视为不存在且不加载,即,不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失. visibility:hidden隐藏,但在浏览时保留位置,即,使对象在网页上不可见,但该对 ...

  5. Openjudge计算概论-角谷猜想

    /*===================================== 角谷猜想 总时间限制: 1000ms 内存限制: 65536kB 描述 所谓角谷猜想,是指对于任意一个正整数,如果是奇数 ...

  6. OpenJudge计算概论-细菌的战争

    /*====================================================================== 细菌的战争 总时间限制: 1000ms 内存限制: 6 ...

  7. 取消GridView/ListView item被点击时的效果

    方法一,在控件被初始化的时候设置 ? 1 2 gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); listView.setSelec ...

  8. 使用async属性异步加载执行JavaScript

    HTML5让我兴奋的一个最大的原因是,它里面实现的新功能和新特征都是我们长久以来一直期待的.比如,我以前一直在使用placeholders,但以前必须要用JavaScript实现.而HTML5里给Ja ...

  9. MongoDB shell 格式化

    直接的方法: db.collection.find().pretty(); 如果想要所有的查询都格式化,可以执行: echo "DBQuery.prototype._prettyShell ...

  10. HTML5 javascript修改canvas的大小

    方法1: 设定固定的值,这种方式跟在html中设定canvas的值没有什么区别: window.onload = function(){ canvas.height = 100; canvas.wid ...