/*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. linux 大并发下 内核优化

     To support over 500k users, you *need* - A 64 bits hardware/kernel (AMD64, Opterons) - At least 8GB ...

  2. Jquery easyui的validatebox控件和正则表达式

    http://blog.csdn.net/dandanzmc/article/details/36421465 仔细观察jquery.validatebox.js文件,会发现它的验证其实还是采用的正则 ...

  3. easyUI之layout

    此组件与easyUI中的其它组件加载的方式相同,载为class方式和js方式,但此组件更多的是用class方式,其它的用js方式更为灵活.它继承panel组件及resize组件. 包括多个<di ...

  4. linux服务之ntp与chrony

    centos7.2变成了chrony RHEL从7.0开始改用chrony同步时间,原ntp同步方式也可以使用,但要安装ntp服务. [root@1st-kvm plymouth]# rpm -qa| ...

  5. html之head,base,meta,title

    一个简单的HTML最基本的必须的元素 用于定义文档的头部,是所有头部元素的容器.头部描述了文档的各种属性和信息,绝大多数头部的数据都不会直接显示给读者. 下面这些标签可用在head部分:base,li ...

  6. java中的分支

    条件语句:     if-else选择结构:         if(条件块){             代码块1         }else{             代码块2         }   ...

  7. Java Dns Cache Manipulator

    通过代码直接设置Java的DNS(实际上设置的是DNS Cache),支持JDK 6+.  功能 设置/重置DNS(不会再去Lookup DNS) 可以设置单条 或是通过Properties文件批量设 ...

  8. DBA日常SQL之查询数据库运行状况

    ,) Day, ,),,)) H00, ,),,)) H01, ,),,)) H02, ,),,)) H03, ,),,)) H04, ,),,)) H05, ,),,)) H06, ,),,)) H ...

  9. 详解Android首选项框架ListPreference

    详解Android首选项框架ListPreference 原文地址 探索首选项框架 在深入探讨Android的首选项框架之前,首先构想一个需要使用首选项的场景,然后分析如何实现这一场景.假设你正在编写 ...

  10. ef 高级操作

    一:动态拼接条件查询 var expression = PredicateBuilder.True<OQC_MES_INF_UL_QMS_OFFLINE>(); SYS_ROLES_CON ...