Windows平台下基于Select模型的服务器
来源:互联网 发布:深度linux系统写python 编辑:程序博客网 时间:2024/05/12 15:09
// 基于 select 模型的socket 编程
#include "stdafx.h"
#include <winsock2.h>
#include <iostream>
#pragma comment( lib, "ws2_32.lib" )
using namespace std;
enum
{
MAIN_RETURN_ERROR = -1,
MAIN_RETURN_NORMAL = 0,
};
BOOL CreateSocketInformation( SOCKET s );
void FreeSocketInfomation( DWORD Index );
// WSABUF 是WinSock2 中定义的 结构体,用于保存缓冲区的长度和地址
// struct _WSABUF
// {
// u_long len; // 缓冲区的长度
// char FAR* buf; // 缓冲区的指针
// };
const static int DATA_BUF_SIZE = 256;
struct _SOCKET_INFOMATION
{
char Buffer [DATA_BUF_SIZE]; // 发送和接收数据缓冲区
WSABUF DataBuf ; // 定义发送和接收数据缓冲区,保护缓冲区在内的长度和内容
SOCKET Socket ; // 与客户端进行通信的 socket
DWORD BytesSEND ; // 保存socket 发送字节数
DWORD BytesRECV ; // 保存socket 接收字节数
};
typedef _SOCKET_INFOMATION SOCKET_INFOMATION;
typedef _SOCKET_INFOMATION* LPSOCKET_INFOMATION;
const static int BUF_SIZE = 256;
DWORD TotalSockets = 0;
LPSOCKET_INFOMATION SocketArray[ FD_SETSIZE];
int _tmain( int argc , _TCHAR* argv[])
{
// 初始化Winsock 2.2
WSADATA wsaData ;
if( WSAStartup ( MAKEWORD( 2, 2 ), & wsaData ) != 0 )
{
cout<<"WSAStartup 无法初始化 !" <<endl ;
return MAIN_RETURN_ERROR ;
}
// 通过WinSock 实现网络通信
SOCKET AcceptSocket ;
SOCKET ListenSocket ;
// 创建用于监听的Socket
ListenSocket = WSASocket ( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );
if( INVALID_SOCKET == ListenSocket )
{
cout<<"Socket Failed !" <<" Reson:"<< WSAGetLastError()<<endl ;
WSACleanup();
return MAIN_RETURN_ERROR ;
}
// 设置服务器Socket 地址
SOCKADDR_IN addrServ ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons( 9990 ); // 服务器端口号
addrServ.sin_addr .S_un. S_addr = htonl ( INADDR_ANY );
// 绑定
int retVal ;
retVal = bind ( ListenSocket, ( const struct sockaddr *)&addrServ , sizeof( SOCKADDR_IN ) );
if( SOCKET_ERROR == retVal )
{
cout<<"bind failed !" <<" Reson: "<< WSAGetLastError()<<endl ;
closesocket( ListenSocket );
WSACleanup();
return -1;
}
// 监听
retVal = listen ( ListenSocket, 5 );
if( SOCKET_ERROR == retVal )
{
cout<<"listen failed !" <<" Reson:"<< WSAGetLastError()<<endl ;
closesocket( ListenSocket );
WSACleanup();
return -1;
}
// 设置socket 其为非阻塞模式 , argp 设为非零值
int iModel = 1;
retVal = ioctlsocket ( ListenSocket, FIONBIO, (u_long FAR* )&iModel );
if( SOCKET_ERROR == retVal )
{
cout<<"ioctlsocket failed Reson :"<< WSAGetLastError()<<endl ;
WSACleanup();
return MAIN_RETURN_ERROR ;
}
//
CreateSocketInformation ( ListenSocket );
cout<<"TCP Server Start ... ..." <<endl;
// 循环等待
FD_SET WriteSet ;
FD_SET ReadSet ;
DWORD Total = 0;
DWORD SendBytes , RecvBytes;
while( true )
{
FD_ZERO( &ReadSet );
FD_ZERO( &WriteSet );
FD_SET( ListenSocket , &ReadSet );
for( DWORD i = 0; i < TotalSockets ; ++i )
{
LPSOCKET_INFOMATION SocketInfo = SocketArray [i];
FD_SET( SocketInfo ->Socket, & WriteSet );
FD_SET( SocketInfo ->Socket, & ReadSet );
}
if( ( Total = select( 0, & ReadSet, &WriteSet , NULL, NULL ) ) == SOCKET_ERROR )
{
cout<<"Select Return with Error "<< WSAGetLastError()<<endl ;
return -1;
}
for( DWORD i = 0; i < TotalSockets ; ++i )
{
// SocketInfo 为当前要处理的信息
LPSOCKET_INFOMATION SocketInfo = SocketArray [i];
// 判断当前socket 的可读性,即是否有接入的连接请求可以接收数据
if( FD_ISSET ( SocketInfo-> Socket, &ReadSet ) )
{
// 对于监听来说,可读表示有新的连接请求
if( SocketInfo ->Socket == ListenSocket )
{
Total--;
// 接受连接请求,与客户端进行通信
if( ( AcceptSocket = accept( ListenSocket , NULL, NULL ) ) != INVALID_SOCKET )
{
int NonBlock = 1;
if( ioctlsocket ( AcceptSocket , FIONBIO, ( u_long FAR * )&NonBlock) == SOCKET_ERROR )
{
cout<<"ioctlsocket() failed with error "<< WSAGetLastError()<<endl ;
return -1;
}
if( CreateSocketInformation ( AcceptSocket ) == FALSE )
return -1;
}
else
{
if( WSAGetLastError () != WSAEWOULDBLOCK )
{
cout<<"accept failed with error "<< WSAGetLastError()<<endl ;
return -1;
}
}
}
// 有新的数据到达
else
{
// 如果当前在ReadSet集合中,表明有数据可读
if( FD_ISSET ( SocketInfo-> Socket, &ReadSet ) )
{
-- Total;
memset( SocketInfo ->Buffer, ' ', DATA_BUF_SIZE );
SocketInfo->DataBuf .buf = SocketInfo ->Buffer;
SocketInfo->DataBuf .len = DATA_BUF_SIZE ;
// 接收数据
DWORD Flags = 0;
if( WSARecv ( SocketInfo ->Socket, &( SocketInfo->DataBuf ), 1, &RecvBytes , &Flags, NULL, NULL ) == SOCKET_ERROR )
{
if( WSAEWOULDBLOCK != WSAGetLastError () )
{
cout<<"WSARecv failed with error "<< WSAGetLastError()<<endl ;
FreeSocketInfomation ( i );
}
continue;
}
else
{
SocketInfo->BytesRECV = RecvBytes ;
if( RecvBytes == 0 )
{
FreeSocketInfomation ( i );
continue;
}
else
{
cout<<SocketInfo ->DataBuf. buf<<endl ;
}
}
}
}
}
else
{
// 发送数据
if( FD_ISSET ( SocketInfo-> Socket, &WriteSet ) )
{
-- Total;
SocketInfo->DataBuf .buf = SocketInfo ->Buffer + SocketInfo->BytesSEND ;
SocketInfo->DataBuf .len = SocketInfo ->BytesRECV - SocketInfo->BytesSEND ;
if( SocketInfo ->DataBuf. len > 0 )
{
if( WSASend ( SocketInfo ->Socket, &( SocketInfo->DataBuf ), 1, &SendBytes , 0, NULL, NULL ) == SOCKET_ERROR )
{
if( WSAGetLastError () != WSAEWOULDBLOCK )
{
cout<<"WSASend failed with error "<< WSAGetLastError()<<endl ;
FreeSocketInfomation ( i );
}
continue;
}
else
{
SocketInfo->BytesSEND += SendBytes ;
if( SocketInfo ->BytesSEND == SocketInfo->BytesRECV )
{
SocketInfo->BytesRECV = 0;
SocketInfo->BytesSEND = 0;
}
}
}
}
}
}
}
// 最后做一些清理工作
closesocket( ListenSocket );
closesocket( AcceptSocket );
WSACleanup();
system("pause" );
return MAIN_RETURN_NORMAL ;
}
// 创建 SOCKET
BOOL CreateSocketInformation( SOCKET s )
{
LPSOCKET_INFOMATION SI ;
// 为SI 分配空间
if( ( SI = (LPSOCKET_INFOMATION) GlobalAlloc( GPTR , sizeof ( SOCKET_INFOMATION ) ) ) == NULL )
{
cout<<"GlobalAlloc Failed with Error "<< GetLastError();
return FALSE ;
}
SI->Socket = s;
SI->BytesSEND = 0;
SI->BytesRECV = 0;
SocketArray[TotalSockets ] = SI;
++ TotalSockets;
return TRUE ;
}
void FreeSocketInfomation( DWORD Index )
{
LPSOCKET_INFOMATION SI = SocketArray[ Index];
DWORD i ;
closesocket( SI ->Socket );
GlobalFree( SI );
for( i = Index; i < TotalSockets ; ++i )
SocketArray[i ] = SocketArray[ i+1];
-- TotalSockets;
}
客户端1:
客户端2
服务器:
没有实现收到 服务端把数据发回客户端。
0 0
- Windows平台下基于Select模型的服务器
- 基于Select模型的Socket服务器
- 基于select模型的TCP服务器
- Windows平台下WSAAsyncSelect 模型 服务器
- Windows平台下 IO模型 服务器
- Windows平台下 WSAEventSelect模型 服务器
- Windows下select模型
- 一个windows下基于select多路分离器的Reactor模型
- 基于select模型tcp服务器的掉线处理
- Windows平台下基于WFP模型的网络防火墙设计实现
- Windows平台下CVS服务器的设置
- windows下实现socket 的 通讯的 select 模型
- Windows与Linux下的select网络模型对比分析
- 服务器Select模型的实现
- select模型的服务器源码
- 基于select模型的tcp服务器---一个服务器如何与多个客户端进行通信?
- 加固基于Windows 2003平台的WEB服务器配置
- 如何加固基于Windows 2003平台的WEB服务器
- Cracking the coding interview--Q2.4
- eclipse导入项目,项目名出现红叉的情况
- jaxb根据*.xsd文件生成相应的java类
- VC++封装FFT DLL
- 获取文件占用空间大小
- Windows平台下基于Select模型的服务器
- android 添加 新建 增加 新增 联系人
- 在布局中引用通用到js,或者css
- 信息保障
- ListView点击列头排序功能实现
- Windows平台下WSAAsyncSelect 模型 服务器
- usb 1-1: device descriptor read/64, error -62
- jquery实现tr元素的上下移动
- BMP文件结构