标签:
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <time.h>
#include <winsock2.h>
#include <stdio.h>
#define PORT 5122
#define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[FD_SETSIZE];
DWORD WINAPI WorkerThread(LPVOID lpParameter);
int main()
{
WSADATA wsaData;
DWORD dwThreadId;
// Initialize Windows socket library
WSAStartup(0x0202, &wsaData);
// Create worker thread
HANDLE hThread = CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int i;
fd_set fdread;
fd_set fdwrite;
fd_set fdexp;
int ret;
struct timeval tv = { 3, 0 };
char szMessage[MSGSIZE];
for (int i = 0; i < 10; ++i)
{
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
SOCKADDR_IN local;
local.sin_addr.S_un.S_addr = inet_addr("206.246.122.250");//连接时间服务器
local.sin_family = AF_INET;
local.sin_port = htons(13);
g_CliSocketArr[g_iTotalConn++] = s;
int ret = connect(s, (sockaddr*)&local, sizeof(SOCKADDR));
printf("connnect ret = %d \n", ret);
}
int n = 0;
while (TRUE)
{
if (n++ >50)
{
break;
}
printf("loop %d\n", n);
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexp);
for (i = 0; i < g_iTotalConn; i++)
{
FD_SET(g_CliSocketArr[i], &fdread);
FD_SET(g_CliSocketArr[i], &fdwrite);
FD_SET(g_CliSocketArr[i], &fdexp);
} // We only care read event
int tick = GetTickCount();
ret = select(0, &fdread, &fdwrite, &fdexp, &tv);//因为fdwrite中的socket一般都是可写的,所以都会立即返回,打印0
printf("select use %d tick \n", GetTickCount() - tick);//机子上打印都是
if (ret == 0)
{ // Time expired
continue;
}
else if (ret < 0)
{
Sleep(100);
continue;
}
for (i = 0; i < g_iTotalConn; i++)
{
if (FD_ISSET(g_CliSocketArr[i], &fdread))
{ // A read event happened on g_CliSocketArr
ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);
if (ret == SOCKET_ERROR)
{
// Client socket closed
printf("Client socket %d closed.\n", g_CliSocketArr[i]);
closesocket(g_CliSocketArr[i]);
if (i < g_iTotalConn - 1)
{
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
}
}
else if (ret == 0)
{
continue;
}
else
{
// We received a message from client
szMessage[ret] = ‘\0‘;
printf("[%s] from %d\n",szMessage, g_CliSocketArr[i]);
}
} //if
if (FD_ISSET(g_CliSocketArr[i], &fdwrite))
{
printf("write %d\n",g_CliSocketArr[i]);
send(g_CliSocketArr[i], "hello", strlen("hello"), 0);//注释掉这行代码的话会一直执行到这里printf,否则下次循环会有异常即会执行下面的代码
}
if (FD_ISSET(g_CliSocketArr[i], &fdexp))
{
printf("except %d\n",g_CliSocketArr[i]);
closesocket(g_CliSocketArr[i]);
if (i < g_iTotalConn - 1)
{
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];//可能是对端关闭socket造成
}
}
}//for
}//while
return 0;
}
socket中select里面的fdread不用解释,简单的就是被connection或者有数据需要recv时返回,而fdwrite的话如果socket内核写缓冲区可用的话会返回告知,具体看上面的代码,网上复制简单修改主要是用于验证,代码说明一切
标签:
原文地址:http://www.cnblogs.com/UnGeek/p/4230504.html