服务器端对一个客户端来了就开启一个工作线程,最多可接受64个。
具体看代码:
#pragma once
#include <winsock.h>
#include <stdio.h> #pragma comment(lib, "ws2_32.lib") #define MaxClient 64 class MyTCPSocket
{
public:
MyTCPSocket(void);
~MyTCPSocket(void);
bool Init();
bool UnInit();
bool CreateSocket();
bool Bind(unsigned aPost,const char* aAdress);
bool Listen(int aBacklog=);
bool Connect(unsigned aPost,const char* aAdress);
bool Send(const char* aBuf);
bool Recv();
void Accept();
static DWORD WINAPI WorkerFun(PVOID aData); public:
SOCKET m_ClientSocket[MaxClient]; private:
SOCKET m_Socket; sockaddr_in m_SockClientaddrIn ;
HANDLE m_ClientHandle[MaxClient];
CRITICAL_SECTION m_CriticalSection;
DWORD m_Thread[MaxClient];
int m_TotClient;
};
#include "MyTCPSocket.h" struct Para
{
MyTCPSocket* m_pMyTCPSocket;
SOCKET m_CurSocket;
}; MyTCPSocket::MyTCPSocket(void)
:m_Socket(INVALID_SOCKET)
, m_TotClient(-)
{
InitializeCriticalSection(&m_CriticalSection);
} MyTCPSocket::~MyTCPSocket(void)
{
EnterCriticalSection(&m_CriticalSection);
for (int i =; i < m_TotClient;++i)
{
if (NULL != m_ClientHandle[i])
{
CloseHandle(m_ClientHandle[i]);
}
}
LeaveCriticalSection(&m_CriticalSection); DeleteCriticalSection(&m_CriticalSection);
} bool MyTCPSocket::Init()
{
int iResult;
WORD wVersionRequested;
WSADATA wsaData; wVersionRequested = MAKEWORD(, );
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != )
{
printf("WSAStartup failed with error: %d\n", iResult);
return false;
}
else
{
printf("WSAStartup succeeded!\n");
return true;
}
} bool MyTCPSocket::CreateSocket()
{
m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == m_Socket)
{
printf("INVALID_SOCKET\n");
return false;
}
printf("Create Socket(%d) successully.\n",m_Socket);
BOOL reuseaddr=TRUE;
setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuseaddr,sizeof(reuseaddr));
return true;
} bool MyTCPSocket::Bind(unsigned aPost,const char* aAdress)
{
struct sockaddr_in server_addr; // server address information
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(aPost); // short, network byte order
server_addr.sin_addr.s_addr = inet_addr(aAdress); // automatically fill with my IP
memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
if (- == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
printf("Bind Error.\n");
return false;
} int nRecvBuf = * ; //设置为32K
if (setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) == -) {
perror("setsockopt");
exit();
}
return true;
} bool MyTCPSocket::Connect( unsigned aPost,const char* aAdress )
{
sockaddr_in lsockaddr_in;
lsockaddr_in.sin_family = AF_INET;
lsockaddr_in.sin_port = htons(aPost);
lsockaddr_in.sin_addr.s_addr = inet_addr(aAdress); if (- == connect(m_Socket,(struct sockaddr *)&lsockaddr_in,sizeof(lsockaddr_in)))
{
printf("Conenct Error.\n");
return false;
}
return true;
} bool MyTCPSocket::Listen( int aBacklog/*=5*/ )
{
if (- == listen(m_Socket,aBacklog))
{
printf("Listen Error.\n");
return false;
}
return true;
} bool MyTCPSocket::Send( const char* aBuf)
{
if (- == send(m_Socket,aBuf,strlen(aBuf)+,))
{
printf("Send Error.\n");
return false;
}
return true;
} bool MyTCPSocket::Recv()
{
//char lBuf[2048];
//int lLength = 0;
//lLength = recv(m_ClientSocket,lBuf,sizeof(lBuf),0);
//if (SOCKET_ERROR == lLength || 0 == lLength)
//{
// closesocket(m_ClientSocket);
// return false;
//}
//int lBegin = 0;
//int lEnd = 0;
//for (;lEnd < lLength;++lEnd)
//{
// if ('\0' == lBuf[lEnd])
// {
// char lData[1024];
// int lLen = lEnd-lBegin;
// memcpy(lData,lBuf+lBegin,lLen+1);
// printf("We successfully received %d byte: %s.\n", lLen, lData);
// lBegin = lEnd+1;
// }
//}
//if (lEnd < lLength)
//{
// char lData[1024];
// memcpy(lData,lBuf+lBegin,lEnd-lBegin);
// lData[lEnd] = '\0';
// printf("We successfully received %d byte: %s.\n", lData);
//}
//return true;
return true;
} bool MyTCPSocket::UnInit()
{
if (- == closesocket(m_Socket))
{
printf("Close Socket Error.\n");
return false;
}
printf("Close Socket(%d).\n",m_Socket);
return true;
} void MyTCPSocket::Accept()
{
while(true)
{
int lAddrLen = sizeof(m_SockClientaddrIn); if (m_TotClient == MaxClient-)
{
printf("Exceed max clients.\n");
break;
} EnterCriticalSection(&m_CriticalSection);
m_ClientSocket[++m_TotClient] = accept(m_Socket, (sockaddr*)&m_SockClientaddrIn,&lAddrLen); Para* lpPara = new Para;
lpPara->m_pMyTCPSocket = this;
lpPara->m_CurSocket = m_ClientSocket[m_TotClient];
LeaveCriticalSection(&m_CriticalSection); printf("We successfully got a connection from %s:%d.\n",
inet_ntoa(m_SockClientaddrIn.sin_addr), ntohs(m_SockClientaddrIn.sin_port)); m_ClientHandle[m_TotClient] = ::CreateThread(NULL, , WorkerFun,PVOID(lpPara), , &m_Thread[m_TotClient]); printf("Create WorkThread(%x) success.\n",m_Thread[m_TotClient]);
}
} DWORD WINAPI MyTCPSocket::WorkerFun( PVOID aData )
{
if (NULL == aData)
{
printf("Exit Thread.\n");
return ;
} Para* lpPara = (Para*)(aData);
MyTCPSocket* lTCPSocket = lpPara->m_pMyTCPSocket; if (lpPara->m_CurSocket == INVALID_SOCKET)
{
return ;
} while(true)
{
char lBuf[];
int lLength = ;
lLength = recv(lpPara->m_CurSocket,lBuf,sizeof(lBuf),);
if (SOCKET_ERROR == lLength || == lLength)
{
closesocket(lpPara->m_CurSocket);
delete lpPara;
printf("Exit Thread.\n");
return ;
}
int lBegin = ;
int lEnd = ;
for (;lEnd < lLength;++lEnd)
{
if ('\0' == lBuf[lEnd])
{
char lData[];
int lLen = lEnd-lBegin;
memcpy(lData,lBuf+lBegin,lLen+);
printf("We successfully received %d byte: %s.\n", lLen, lData);
lBegin = lEnd+;
}
}
if (lEnd < lLength)
{
char lData[];
memcpy(lData,lBuf+lBegin,lEnd-lBegin);
lData[lEnd] = '\0';
printf("We successfully received %d byte: %s.\n", lData);
}
} return ;
}
表示是很简陋的写法,肯定还是有问题的,同步的地方没怎么想清楚,测试代码可以看上一篇的介绍,好吧,今天暂时先写到这里,尼玛,公司写神码软件申请书,搓的一逼。
一个worker thread服务一个客户端的更多相关文章
-
ROS学习笔记11-写一个简单的服务和客户端(C++版本)
本文主要来源于:http://wiki.ros.org/ROS/Tutorials/WritingServiceClient%28c%2B%2B%29 写一个服务节点.在创建消息和服务中,我们创建了一 ...
-
曹工杂谈:花了两天时间,写了一个netty实现的http客户端,支持同步转异步和连接池(1)--核心逻辑讲解
背景 先说下写这个的目的,其实是好奇,dubbo是怎么实现同步转异步的,然后了解到,其依赖了请求中携带的请求id来完成这个连接复用:然后我又发现,redisson这个redis客户端,底层也是用的ne ...
-
Windows Azure入门教学系列 (三):创建第一个Worker Role程序
在开始本教学之前,请确保你从Windows Azure 平台下载下载并安装了最新的Windows Azure开发工具.本教学使用Visual Studio 2010作为开发工具. 步骤一:创建解决方案 ...
-
多线程编程学习笔记——编写一个异步的HTTP服务器和客户端
接上文 多线程编程学习笔记——使用异步IO 二. 编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...
-
从零讲解搭建一个NIO消息服务端
本文首发于本博客,如需转载,请申明出处. 假设 假设你已经了解并实现过了一些OIO消息服务端,并对异步消息服务端更有兴趣,那么本文或许能带你更好的入门,并了解JDK部分源码的关系流程,正如题目所说,笔 ...
-
服务注册中心之ZooKeeper系列(二) 实现一个简单微服务之间调用的例子
上一篇文章简单介绍了ZooKeeper,讲了分布式中,每个微服务都会部署到多台服务器上,那服务之间的调用是怎么样的呢?如图: 1.集群A中的服务调用者如何发现集群B中的服务提供者呢? 2.集群A中的服 ...
-
如何设计一个异步Web服务——任务调度
接上一篇<如何设计一个异步Web服务——接口部分> Application已经将任务信息发到了Service服务器中,接下来,Service服务器改如何对自身的资源进行合理分配以满足App ...
-
WCF入门教程(四)通过Host代码方式来承载服务 一个WCF使用TCP协议进行通协的例子 jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding System.ServiceModel.WSHttpBinding协议 学习WCF笔记之二 无废话WCF入门教程一[什么是WCF]
WCF入门教程(四)通过Host代码方式来承载服务 Posted on 2014-05-15 13:03 停留的风 阅读(7681) 评论(0) 编辑 收藏 WCF入门教程(四)通过Host代码方式来 ...
-
eShopOnContainers 是一个基于微服务的.NET Core示例框架
找到一个好的示例框架很难,但不是不可能.大多数是小型Todo风格的应用程序,通常基于SimpleCRUD.值得庆幸的是,Microsoft已经为eShopOnContainers创建了一个基于微服务的 ...
随机推荐
-
fatal error C1083: Cannot open include file: &#39;qttreepropertybrowser.moc&#39;: No such file or directory
编译QtPropertyBrowser的时候出错.要用moc来生成.moc文件.我好奇的是与之前的通过.h生成moc_xxx.cpp不一样. 要用以下命令.一般来说是处理带Q_OBJECT宏的.h文件 ...
-
windows下使用批处理调用exe和服务
手动调用exe或者启动服务很麻烦,可以使用.bat批处理文件,双击运行即可.步骤如下:创建一个新的txt文件但是保存成.bat结尾的文件(选择用记事本打开编写命令),输入代码内容格式如下: @echo ...
-
Luogu5176 公约数 莫比乌斯反演、线性筛
传送门 好像是我们联考时候的题目? 一个结论:\(\gcd(ij,ik,jk) \times \gcd(i,j,k) = \gcd(i,j) \times \gcd(i,k) \times \gcd( ...
-
vue-百度地图-maker文字标签显示隐藏
html: <div id="allmap" class="map"></div> script: mounted() { th ...
-
suse 11 pip pip3使用过程中遇到的各种问题
在安装完成python3.6后,使用pip3安装某些插件,报如下错误 linux-9qk9:~ # pip3 install ipython pip is configured with locati ...
-
Spring MVC 使用介绍(三)—— Controller接口控制器
一.概述 Controller接口类图如下,其中,BaseCommandController已从Spring 4移除 基于继承Controller接口的方式已经不推荐使用,仅供学习参考 二.基于Con ...
-
odoo开发笔记 -- 字段增加唯一约束
前台违反约束效果: 后台模型中定义代码: name = fields.Char(string="Name", copy=False) # 流水号 _sql_constraints ...
-
poi导出excel 并处理插入网络图片 范例 处理文件下载中文乱码
package com.inborn.inshop.controller.product; import com.inborn.inshop.common.util.DateUtils;import ...
-
np.identity()
二.np.identity()这个函数和之前的区别在于,这个只能创建方阵,也就是N=M 函数的原型:np.identity(n,dtype=None) 参数:n,int型表示的是输出的矩阵的行数和列数 ...
-
asp.net六种方法刷新页面
第一: private void Button1_Click( object sender, System.EventArgs e ) { Response.Redirect( Reque ...