选择模型:Select(选择)模型是Winsock中最常见的I/O模型



/********************************************************************
created: 2016/09/23
created: 23:9:2016   9:04
filename: D:\code\SocketClassify\SocketClassify\TCPServ_SelectModel.h
file path: D:\code\SocketClassify\SocketClassify
file base: TCPServ_SelectModel
file ext: h
author: singebogo


purpose: 选择模型:Select(选择)模型是Winsock中最常见的I/O模型
Function:
Function:
Note:
Note:
*********************************************************************/
#pragma once


#ifndef __I_TCPSERV_SELECTMODEL
#define __T_TCPSERV_SELECTMODEL


/****************************头文件库*******************************/
#include "socket/UsrSocket.h"


#include<iostream>


using namespace std;






/****************************宏定义*********************************/
#define  IPPORT 4000 // ip 端口
#define  MAXBACKLOG SOMAXCONN // 客户最大连接数




/****************************函数实现*******************************/
#ifdef __cplusplus
extern "C" {
#endif


int g_itotalconn = 0; // 连接数量singre
SOCKET g_clientsocketarry[FD_SETSIZE] = {0}; //套接字数组


DWORD WINAPI WorkerThread(LPVOID lpParam); //线程  




void CreateTcpServ_SelectModel()
{
CUsrSocket us_socket;


CUsrSocket::_STOCKET _socket_param;
_socket_param._af = AF_INET;
_socket_param._protocol = SOCK_STREAM;
_socket_param._type = 0;


CUsrSocket::_SOCKET_ADDR _socket_addrparam;
_socket_addrparam._b_addrany = true;
_socket_addrparam._i_port = IPPORT;
_socket_addrparam._str_ip = "";


DWORD dw_threadid;


// 初始化套接字
if(us_socket.InitWSAData(us_socket._wVersionRequested, us_socket._wsaData))
{
cout<<"InitWSAData successed!"<<endl;
}else{
cout<<"InitWSAData fauiled!"<<endl;
return;
}


// 创建套接字对象
us_socket._socket_no = us_socket.CreateSocket(_socket_param._af, _socket_param._protocol, _socket_param._type);


// 设置套接字地址
us_socket._socket_addr = us_socket.SetSocketAddr(_socket_addrparam._b_addrany , 
_socket_addrparam._str_ip, _socket_addrparam._i_port);


// bind
us_socket.SocketBind(us_socket._socket_no, us_socket._socket_addr);


// listen
us_socket.SocketListen(us_socket._socket_no, MAXBACKLOG);


// Create worker thread  
//创建线程   
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dw_threadid);  




while (1)
{
us_socket._socket_conn = us_socket.SocketAccept(us_socket._socket_no, us_socket._socket_client);
if (us_socket._socket_conn == INVALID_SOCKET)
continue;
else{
//这里client的SOCKADDR_IN  client 中可以取出IP  
cout<<"Accepted client:" <<inet_ntoa(us_socket._socket_client.sin_addr)<<ntohs(us_socket._socket_client.sin_port)<<endl;  
// Add socket to g_clientsocketarry  
//把客户端套接字放入数组中  
g_clientsocketarry[g_itotalconn++] = us_socket._socket_conn;  


//-send-
char sendBuf[DEFAULT_BUFLEN];  
memset(sendBuf, 0 , DEFAULT_BUFLEN);
sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(us_socket._socket_client.sin_addr));//inet_ntoa网络地址转换转点分十进制的字符串指针  
send(us_socket._socket_conn, sendBuf, strlen(sendBuf)+1,0);
}
}
return;
}


DWORD WINAPI WorkerThread(LPVOID lpParam)//线程  
{  
int            i;  
fd_set         fdread;//结构  
int            ret;  
struct timeval tv = { 1, 0 };//超时时间 SELECT模型中用到的这里是1秒  
char           szMessage[DEFAULT_BUFLEN];//信息数组,事实上就是个缓冲区  
memset(szMessage, 0, DEFAULT_BUFLEN);


while (TRUE)  
{  


FD_ZERO(&fdread);//清空fd_set结构  
for (i = 0; i < g_itotalconn; i++)  
{  
FD_SET(g_clientsocketarry[i], &fdread);//把客户套接字放到SELECT要求的数组中  
}  


//**************************************  
// We only care read event  
//只关心读的情况  
ret = select(0, &fdread, NULL, NULL, &tv);  
if (ret == 0)  
{  
// Time expired 超时 
continue;  
}  


//如果SELECT返回不是0  
for (i = 0; i < g_itotalconn; i++)  
{  
if (FD_ISSET(g_clientsocketarry[i], &fdread))  
{  
// A read event happened on g_clientsocketarry[i]  
//一个可读发生在这个套接字上  
// 每次接收消息之前都应该将缓存情况
memset(szMessage, 0 , DEFAULT_BUFLEN);
ret = recv(g_clientsocketarry[i], szMessage, DEFAULT_BUFLEN, 0);  
cout<<"ClientNO: "<< g_clientsocketarry[i] <<szMessage<<endl;
//把它读出到缓冲区  
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))  
{  
// Client socket closed  
//客户端关闭  
cout<<"Client socket closed NO: "<< g_clientsocketarry[i]<<endl;  
closesocket(g_clientsocketarry[i]);//关闭这个套接字

if (i <= g_itotalconn - 1)  
{  
//将数组中最后一个套接字挪到当前的位置上     全部的client 删除 还会保留
// 刚好是数组最后一个 出现重复赋值,应该丢弃
if (i == g_itotalconn - 1)
{
g_clientsocketarry[--g_itotalconn] = 0;

else
{
g_clientsocketarry[i--] = g_clientsocketarry[--g_itotalconn];  
}

cout<<g_itotalconn<<endl;
for (int j = 0; j < g_itotalconn; j++)
{
cout<<g_clientsocketarry[j]<<endl;
}
}  
else  
{  
// We received a message from client  
//如果以上没发生,那么就接收到一个客户端的信息  
szMessage[ret] = '\0';  
//直接回送回去  
// send(g_clientsocketarry[i], szMessage, strlen(szMessage), 0);
cout<<"sendLength: "<<send(g_clientsocketarry[i], szMessage, strlen(szMessage), 0)<<endl;  
}  
}  
}  
}  


return 0;  
}  




#ifdef __cplusplus
}
#endif
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值