Windows socket I/O模型 之  select(1)中。我们仅仅是在console中简单的模拟了select的处理方法。

还有非常多特性不能改动。比方仅仅能写,不能读。

没使用线程。也没有同步不同的读写线程。

先谈谈个人眼下对select的理解。

select就是监控一组套接字的变化情况。

比方一个fd_set的变量(暂且定义为fdRead)里面有5个套接字。当你传给select后,如果仅仅有2个被触发。

那么这个fdRead也就改变了。这是为什么select须要从全局fd_set拷贝一份给select的原因。

然后我们依据套接字的变化情况做对应的处理就OK了。可是大并发量还没有測试。

今晚我改进了。以下大家见代码。

。。。

// Select_Server.cpp : Defines the entry point for the console application.
// 服务端 #include "stdafx.h" #define STR_SERVER_IP "127.0.0.1"
#define INT_SERVER_PORT 8001
#define INT_DATABUFFER_SIZE 256 SOCKET g_soClient;
typedef std::list<SOCKET> LstSocket;
LstSocket g_lstSoClient; SOCKET g_soServer;
fd_set g_fdSocketSet; // for thread synchronize
CCriSec g_criSec; DWORD WINAPI ThreadRead(LPVOID lpvParam)
{
int iResult = 0;
sockaddr_in addrAccept;
int iAcceptLen = sizeof(addrAccept);
SOCKET soClient; FD_ZERO(&g_fdSocketSet);
FD_SET(g_soServer, &g_fdSocketSet);
fd_set fdRead, fdWrite;
while( TRUE ) {
// initialize
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
fdRead = g_fdSocketSet;
fdWrite = g_fdSocketSet; int n1 = fdRead.fd_count;
int n2 = fdWrite.fd_count;
int n3 = g_fdSocketSet.fd_count;
int iResult = select(0, &fdRead, &fdWrite, NULL, NULL);
if( iResult == SOCKET_ERROR) {
break;
} if(FD_ISSET(g_soServer, &fdRead)) {
soClient = accept(g_soServer, (sockaddr*)&addrAccept, &iAcceptLen); CCriSecLock lock(g_criSec);
if(soClient == INVALID_SOCKET) {
continue;
} else {
printf("\n[%s:%d] has connected to server!\r\n", inet_ntoa(addrAccept.sin_addr),
ntohs(addrAccept.sin_port));
FD_SET(soClient, &g_fdSocketSet);
}
} else {
// check read
for(int i=0; i < (int)fdRead.fd_count; i++) {
if ( fdRead.fd_array[i] == g_soServer ) {
continue;
} if( FD_ISSET(fdRead.fd_array[i], &g_fdSocketSet) ) {
sockaddr_in name;
int namelen = sizeof(sockaddr_in);
getpeername(fdRead.fd_array[i], (sockaddr *)&name, &namelen); char buf[256] = {0};
int len = 256;
int ret = recv(fdRead.fd_array[i], buf, len, 0);
CCriSecLock lock(g_criSec);
if( ret == SOCKET_ERROR ) {
int nErr = GetLastError();
if( nErr == 10054 ) {
// Connection reset by peer.
FD_CLR(fdRead.fd_array[i], &g_fdSocketSet);
printf("\n[%s:%d] disconnect from server.\n", inet_ntoa(name.sin_addr), ntohs(name.sin_port) );
} else {
printf("\nfdread failed with %d\n", nErr);
}
} else {
printf("\nRecv from [%s:%d] : %s\n", inet_ntoa(name.sin_addr), ntohs(name.sin_port), buf);
}
}
} // check write
static bool b11 = false;
for(int i=0; i < (int)fdWrite.fd_count; i++) {
if( FD_ISSET(fdWrite.fd_array[i], &g_fdSocketSet) ) {
char buf[256] = "abcd";
int len = 256;
if( !b11 ) {
b11 = true;
//send(fdWrite.fd_array[i], buf, len ,0);
}
}
}
}
} return 0;
} DWORD WINAPI ThreadWrite(LPVOID lpvParam)
{
std::string str;
{
CCriSecLock lock(g_criSec);
std::cout << "Please input message to client: ";
}
while( getline(std::cin, str) ) {
if( str.compare("exit") == 0 ) {
{
CCriSecLock lock(g_criSec);
printf("close write thread\n");
}
break;
} for(int i = 1; i < (int)g_fdSocketSet.fd_count; i++) {
send(g_fdSocketSet.fd_array[i], str.data(), (int)str.size(), 0);
}
} return 0;
} int _tmain(int argc, _TCHAR* argv[])
{
WORD dwVersion = MAKEWORD(2, 2);
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData); g_soServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == g_soServer) {
printf("Failed to create socket!\r\n");
WSACleanup();
return -1;
} sockaddr_in addrServer;
memset(&addrServer,0,sizeof(sockaddr_in));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(INT_SERVER_PORT);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); int iResult; bool bReuseAddr = true;
iResult = setsockopt(g_soServer, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseAddr, sizeof(bReuseAddr));
if(SOCKET_ERROR == iResult) {
printf("Failed to set resueaddr socket!\r\n");
WSACleanup();
return -1;
} //设置非堵塞方式连接
unsigned long cmd = 1;
iResult = ioctlsocket(g_soServer, FIONBIO, &cmd); iResult = bind(g_soServer, (sockaddr *)&addrServer, sizeof(addrServer));
if (SOCKET_ERROR == iResult) {
printf("Failed to bind address!\r\n");
WSACleanup();
return -1;
} if (0 != listen(g_soServer, 5)) {
printf("Failed to listen client!\r\n");
WSACleanup();
return -1;
} printf("Start server...\r\n"); HANDLE hWorkRead = CreateThread(NULL, 0, ThreadRead, NULL, 0, NULL);
HANDLE hWorkWrite = CreateThread(NULL, 0, ThreadWrite, NULL, 0, NULL); ::WaitForSingleObject(hWorkRead, INFINITE);
::WaitForSingleObject(hWorkWrite, INFINITE); WSACleanup(); return 0;
}

以下是client代码:

// Select_Client.cpp : Defines the entry point for the console application.
// #include "stdafx.h" #define INT_SERVER_PORT 8001
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 256
#define STR_EXIT "exit"
#define STR_RECV "recv" //
SOCKET g_soClient;
fd_set g_fdSocketSet; // for thread synchronize
CCriSec g_criSec; DWORD WINAPI ThreadWorker(LPVOID lpvParam)
{
FD_ZERO(&g_fdSocketSet);
FD_SET(g_soClient, &g_fdSocketSet);
fd_set fdRead, fdWrite; while( TRUE ) {
// initialize
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
fdRead = g_fdSocketSet;
fdWrite = g_fdSocketSet; int iResult = select(0, &fdRead, &fdWrite, NULL, NULL);
if( iResult == SOCKET_ERROR) {
break;
} else if( iResult == 0 ) {
printf("Time limit expired\n");
} else {
// check read
if (FD_ISSET(fdRead.fd_array[0], &g_fdSocketSet)) {
sockaddr_in name;
int namelen = sizeof(sockaddr_in);
getpeername(fdRead.fd_array[0], (sockaddr *)&name, &namelen); char buf[256] = {0};
int len = 256;
int ret = recv(fdRead.fd_array[0], buf, len, 0);
CCriSecLock lock(g_criSec);
if( ret == SOCKET_ERROR ) {
int nErr = GetLastError();
if( nErr == 10054 ) {
// Connection reset by peer.
FD_CLR(fdRead.fd_array[0], &g_fdSocketSet);
printf( "\n[%s:%d] is closed.\n", inet_ntoa(name.sin_addr), ntohs(name.sin_port) );
} else {
printf("fdread failed with %d\n", nErr);
}
} else {
CCriSecLock lock(g_criSec);
printf("\nRecv from [%s:%d] : %s\n", inet_ntoa(name.sin_addr), ntohs(name.sin_port), buf);
}
} // check write
if (FD_ISSET(fdWrite.fd_array[0], &g_fdSocketSet)) {
int a=2;
int b=a;
}
}
} return 0;
} void main(void)
{
WSAData wsaData;
WSAStartup(WINSOCK_VERSION,&wsaData); g_soClient = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == g_soClient) {
printf("Failed to create client!\r\n");
WSACleanup();
} sockaddr_in addrServer;
addrServer.sin_addr.S_un.S_addr = inet_addr(STR_SERVER_IP);
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(INT_SERVER_PORT); int iResult; //设置非堵塞方式连接
//unsigned long ul = 1;
//iResult = ioctlsocket(g_soClient, FIONBIO, (unsigned long*)&ul); iResult = connect(g_soClient, (sockaddr *)&addrServer, sizeof(sockaddr_in));
if (SOCKET_ERROR == iResult) {
printf("Failed to connect server!(Error: %d)\r\n", ::WSAGetLastError());
WSACleanup();
return;
} HANDLE hWorker = CreateThread(NULL, 0, ThreadWorker, NULL, 0, NULL); std::string str;
std::cout << "Please input message to server: ";
while( getline(std::cin, str) ) {
send(g_soClient, str.data(), str.size(), 0);
std::cout << "Please input message to client: ";
} closesocket(g_soClient);
WSACleanup();
}

头文件

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
// #pragma once #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif #include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <WINSOCK2.H> #pragma comment(lib,"ws2_32.lib") // TODO: reference additional headers your program requires here
#include "CriticalSection.h"

// CriticalSection.h

/*
* Copyright: JessMA Open Source (ldcsaa@gmail.com)
*
* Version : 2.3.2
* Author : Bruce Liang
* Website : http://www.jessma.org
* Project : https://github.com/ldcsaa
* Blog : http://www.cnblogs.com/ldcsaa
* Wiki : http://www.oschina.net/p/hp-socket
* QQ Group : 75375912
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ /****************************************************************************
* *
* CriticalSection.h *
* *
* Create by : *
* Kingfisher 2003-10-15 *
* *
* Description: *
* 封装Win32临界量对象和相互排斥量内核对象 *
****************************************************************************/ #pragma once #include <windows.h> class CCriSec
{
public:
CCriSec() {::InitializeCriticalSection(&m_crisec);}
~CCriSec() {::DeleteCriticalSection(&m_crisec);} void Lock() {::EnterCriticalSection(&m_crisec);}
void Unlock() {::LeaveCriticalSection(&m_crisec);} private:
CCriSec(const CCriSec& cs);
CCriSec operator = (const CCriSec& cs); private:
CRITICAL_SECTION m_crisec;
}; class CCriSec2
{
public:
CCriSec2(BOOL bInitialize = TRUE)
{
if(bInitialize)
{
m_pcrisec = new CRITICAL_SECTION;
::InitializeCriticalSection(m_pcrisec);
}
else
m_pcrisec = NULL;
} ~CCriSec2() {Reset();} void Attach(CRITICAL_SECTION* pcrisec)
{
Reset();
m_pcrisec = pcrisec;
} CRITICAL_SECTION* Detach()
{
CRITICAL_SECTION* pcrisec = m_pcrisec;
m_pcrisec = NULL;
return pcrisec;
} void Lock() {::EnterCriticalSection(m_pcrisec);}
void Unlock() {::LeaveCriticalSection(m_pcrisec);} private:
CCriSec2(const CCriSec2& cs);
CCriSec2 operator = (const CCriSec2& cs); void Reset()
{
if(m_pcrisec)
{
::DeleteCriticalSection(m_pcrisec);
delete m_pcrisec;
m_pcrisec = NULL;
}
} private:
CRITICAL_SECTION* m_pcrisec;
}; template<class CLockObj> class CLocalLock
{
public:
CLocalLock(CLockObj& obj) : m_lock(obj) {m_lock.Lock();}
~CLocalLock() {m_lock.Unlock();}
private:
CLockObj& m_lock;
}; typedef CLocalLock<CCriSec> CCriSecLock;
typedef CLocalLock<CCriSec2> CCriSecLock2;

Windows socket I/O模型 之 select(2)的更多相关文章

  1. Windows Socket I/O模型

    老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里.这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socket I/O模型~~~ 一:s ...

  2. Socket I/O模型之select模型

    socket网络编程中有多种常见的I/O模型: 1.blocking阻塞 2.nonblocking非阻塞 3.I/O multiplexing复用 4.signal driven 5.asynchr ...

  3. 转:Windows Socket五种I/O模型

    原文转自:  Windows Socket五种I/O模型 Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模 ...

  4. Windows Socket五种I/O模型

    转载:http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813637.html 如果你想在Windows平台上构建服务器应用,那么I/O模 ...

  5. windows下的IO模型之选择(select)模型

    1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作. 选择模型的核心是FD_SET集合和select函数.通过该函数,我们可以 ...

  6. c++ 网络编程(八) LINUX-epoll/windows-IOCP下 socket opoll函数用法 优于select方法的epoll 以及windows下IOCP 解决多进程服务端创建进程资源浪费问题

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9622548.html 锲子:关于并发服务器中的I/O复用实现方式,前面在网络编程系列四还是五来 ...

  7. Windows Socket五种I/O模型——代码全攻略(转)

    Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...

  8. 高性能 Windows Socket 组件 HP-Socket v3.0.2 正式发布

    HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...

  9. 高性能 Windows Socket 组件 HP-Socket v3.0.1 正式发布

    HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...

随机推荐

  1. redis安装、配置和启动

    一.运行环境 1.vmware虚拟机上的centos7系统,安装步骤略,网上搜搜就有,连接工具:secureCRT 2.新安装的linux,是没有wget命令,所以先执行这个命令安装下:yum -y ...

  2. Oracle PL/SQL 语言(Procedural Language/SQL)

    Oracle PL/SQL 语言(Procedural Language/SQL)是结合了结构化查询与 Oracle 自身过程控制为一体的强大语言,PL/SQL 不但支持更多的数据类型,拥有自身的变量 ...

  3. 换肤功能的实现以及监听storage实现多个标签页一起换肤

    1:需求:项目的侧边栏实现换肤功能,核心代码: updateSkin (val) { const existSkinLink = document.head.querySelector('link[i ...

  4. php-超全局变量

    下表列出了您能够在 $_SERVER 中访问的最重要的元素: 元素/代码 描述 $_SERVER[' PHP_SELF '] 返回当前执行脚本的文件名. $_SERVER[' GATEWAY_INTE ...

  5. JS实现并集,交集和差集

    var set1 = new Set([1,2,3]);var set2 = new Set([2,3,4]); 并集let union = new Set([...set1, ...set2]); ...

  6. 谈谈自己对REST、SOA、SOAP、RPC、ICE、ESB、BPM知识汇总及理解(转载)

    相关参考文章: 谈谈自己对REST.SOA.SOAP.RPC.ICE.ESB.BPM知识汇总及理解 微服务SOA架构与RPC远程过程调用 SOA和微服务架构的区别 SOA: 维基百科解释:SOA:面向 ...

  7. Mysql多列索引实践

    在网上看到: 定义:最左前缀原则指的的是在sql where 子句中一些条件或表达式中出现的列的顺序要保持和多索引的一致或以多列索引顺序出现,只要 出现非顺序出现.断层都无法利用到多列索引. 该博文有 ...

  8. C语言实验设计

    一.实验题目,设计思路,实现方法 7-4 计算分段函数[2](10 分) 本题目要求计算下列分段函数f(x)的值: 注:可在头文件中包含math.h,并调用sqrt函数求平方根,调用pow函数求幂. ...

  9. 转 整理 Linux服务器部署系列之一—Apache篇

    花了差不多一天,参考了几个博客,终于初步配成功了 Apache,先总结一下: 如果apache安装成为linux的服务的话,可以用以下命令操作: service httpd start 启动 serv ...

  10. HDU 4722:Good Numbers(数位DP)

    类型:数位DP 题意:定义一个Good Number 为 一个数所有位数相加的和%10==0.问[A,B]之间有多少Good Number. 方法: 正常“暴力”的定义状态:(i,d,相关量) 定义d ...