socket模型处理多个客户端
最近学完了简单的socket编程,发现其实socket的网络编程其实并没有什么难度,只是简单的函数调用,记住客户端与服务端的步骤,写起来基本没有什么问题。
在服务器程序的设计中,一个服务器不可能只相应一个客户端的链接,为了响应多个客户端的链接,需要使用多线程的方式,每当有一个客户端连接进来,我们就开辟一个线程,用来处理双方的交互(主要是利用recv或者recvfrom用于收发信息),由于但是在网络中可能出现这样一种情况:由于处理比较复杂,下一条信息到来之后,上一条信息的处理还没有完成,这样信息太多了之后系统的缓冲占满之后可能会发生丢包的现象,所以为了解决这个问题,需要另外再开一个线程,专门用来处理接收到的数据,这样总共至少有3个线程,主线程,收发信息的线程,处理线程;这样可能也不完整,处理的操作种类多了的话可能需要根据不同的请求来开辟不同的线程用来处理这一类请求,下面是实现这一思路的部分代码:
全局变量:
DWORD WINAPI AcceptThread(LPVOID lpParameter);
DWORD WINAPI RecvThread(LPVOID lpParameter);
DWORD g_nAcceptID = 123;
DWORD g_nRecvID = 234;
HANDLE g_hAccpetThread;
HANDLE g_hRecvThread;
主线程函数:
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
SOCKET sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (INVALID_SOCKET == sockListen)
{
cout << "创建侦听套接字失败,错误码为:" << WSAGetLastError() << endl;
return -1;
}
SOCKADDR_IN srvAddr = { 0 };
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(6666);
srvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR == bind(sockListen, (SOCKADDR*)&srvAddr, sizeof(SOCKADDR)))
{
cout << "绑定失败,错误码为:" << WSAGetLastError() << endl;
WSACleanup();
return -1;
}
if (SOCKET_ERROR == listen(sockListen, 5))
{
cout << "侦听失败,错误码为:" << WSAGetLastError() << endl;
WSACleanup();
return -1;
}
while (true)
{
SOCKET sockConn = accept(sockListen, NULL, 0);
if (INVALID_SOCKET == sockConn)
{
cout << "本次连接失败,即将进入下一次连接,错误码为:" << WSAGetLastError() << endl;
closesocket(sockConn);
closesocket(sockListen);
WSACleanup();
continue;
}
g_hAccpetThread = CreateThread(NULL, 0, AcceptThread, &sockConn, 0, &g_nAcceptID);
}
WaitForSingleObject(g_hAccpetThread, INFINITE);
WSACleanup();
return 0;
}
收发数据函数:
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
cout << "有客户端连接进来" << endl;
SOCKET sockConn = *(SOCKET*)lpParameter;
while (true)
{
char *pszBuf = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, 255);
if (SOCKET_ERROR == recv(sockConn, pszBuf, 255, 0))
{
cout << "接受数据失败,错误码为:" << WSAGetLastError() << endl;
cout << "准备进行下一次接受数据....." << endl;
continue;
}
g_hRecvThread = CreateThread(NULL, 0, RecvThread, pszBuf, 0, &g_nRecvID);
WaitForSingleObject(g_hRecvThread, INFINITE);
if (0 == strcmp("exit", pszBuf))
{
cout << "正在断开与该客户端的连接" << endl;
HeapFree(GetProcessHeap(), 255, pszBuf);
return 0;
}
}
return 0;
}
信息处理子线程:
DWORD WINAPI RecvThread(LPVOID lpParameter)
{
cout << “接受到客户端的数据:” << (char*)lpParameter << endl;
return 0;
}
虽说这个解决了多个客户端与服务器通信的问题,但是这样写确定也很明显:所有的与客户端通信的socket都有程序员自己管理,无疑加重了程序员的负担;每有一个连接都需要创建一个线程,当有大量的客户端连接进来开辟的线程数是非常多的,线程是非常耗资源的,所以为了解决这些问题就提出了异步的I/O模型,它们解决了这些问题,由系统管理套接字,不要要人为的一个个管理,同时不需要开辟多个线程来处理与客户端的连接,我们可以将线程主要用于处理客户端的请求上;
socket模型处理多个客户端的更多相关文章
- Socket模型详解(转)
两种I/O模式 一.选择模型 二.异步选择 三.事件选择 四.重叠I/O模型 五.完成端口模型 五种I/O模型的比较 两种I/O模式 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待 ...
- 手把手教你玩转SOCKET模型之重叠I/O篇(下)
四. 实现重叠模型的步骤 作 了这么多的准备工作,费了这么多的笔墨,我们终于可以开始着手编码了.其实慢慢的你就会明白,要想透析重叠结构的内部原理也许是要费点功夫,但是只是学会 如何来使用它,却 ...
- 转:变手把手教你玩转SOCKET模型之重叠I/O篇
手把手教你玩转SOCKET模型之重叠I/O篇 “身为一个初学者,时常能体味到初学者入门的艰辛,所以总是想抽空作点什么来尽我所能的帮助那些需要帮助的人.我也希望大家能把自己的所学和他人一起分享,不要去鄙 ...
- 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- socket模型
Socket: "主机" + "端口" = 套接字/插座; 仅仅是一个通信模型,不属于七层协议(网络协议). 一台电脑(IP)的一个应用程序(端口) 和 另一台 ...
- c# TCP/IP协议利用Socket Client通信(只含客户端Demo)
完全是基础,新手可以随意看看,大牛可以关闭浏览页了,哈哈. TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. ...
- JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求
JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求 哇,一看标题怎么这么长啊,其实意思很简单,哥讨厌用HTTP Client做POST与GET提交 觉得那个毕竟是别人写 ...
- 运用socket实现简单的服务器客户端交互
Socket解释: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意 ...
- .NET平台下几种SOCKET模型的简要性能供参考
转载自:http://www.cnblogs.com/asilas/archive/2006/01/05/311309.html .NET平台下几种SOCKET模型的简要性能供参考 这个内容在cnbl ...
随机推荐
- Office 365 机器人(Bot)开发入门
作者:陈希章 发表于 2017年7月29日 前言 作为人工智能技术的一个主要的表现形式,这些年机器人(bot)的应用越来越广泛.不管是有实物的,还是纯软件的,现在的机器人技术应该说已经走入寻常百姓家了 ...
- More DETAILS! PBR的下一个发展在哪里?
最近几年图形学社区对PBR的关注非常高,也许是由于Disney以及一些游戏引擎大厂的助推,也许是因为它可以被轻松集成进实时渲染的游戏引擎当中,也许是因为许多人发现现在只需要调几个参数就能实现具有非常精 ...
- 《软件测试的艺术(原书第2版)》【PDF】下载
<软件测试的艺术(原书第2版)>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196343 内容简介 本书以一次自评价测试开篇,从软 ...
- JS如何实现导航栏的智能浮动
<script language="javascript"> function smartFloat(obj) { var obj = docu ...
- JS画几何图形之一【直线】
JS画图的想法经过大脑的时候,觉得有点意思,所以就实践了一番.JS画图为系列文章,本是讲点.线和面 先看样例:http://www.zhaojz.com.cn/demo/draw5.html 一.点 ...
- MongoDB学习第七篇 --- sql和mongodb对比
一.术语和概念的对比 SQL MongoDB database database row document or BSON document column field index index ...
- ecshop 属性表(attribute)商品属性表(goods_attr)货品表(prduct) 商品数量的联系
ecshop 属性表(attribute)商品属性表(goods_attr)货品表(prduct) 商品数量的联系 一个商城的商品属性存放在属性表(attribute)里 ,每个商品对应的属性在goo ...
- ECMAScript中的两种属性
数据属性 数据属性包含一个数据值的位置.在这个位置可以读取和写入值.数据属性一般用于存储数据数值. 数据属性有4个描述其行为的特征. configurable:true/false,是否可以通过del ...
- JDK8.0新特性
连接转载地址:http://www.2cto.com/kf/201609/544044.html Eclipse: http://aiyiupload.oss-cn-beijing.aliyuncs. ...
- Linux(CentOS6.5)下编译安装Nginx1.10.1
首先在特权账号(root)下安装编译时依赖项: yum install gcc gcc-c++ perl -y 首先以非特权账号(本文以账号comex为例)登陆OS: 进入data目录下载相关安装 ...