新手,请问大家,1:WSAAccept代替accept,并回调自己定义的Condition Function,这个Condition Function怎么搞?
2:连接数是0时,怎么解决cpu100%的情况?
谢谢
14 个解决方案
#1
1.WSAAccept,支持回调函数,在接收到connect请求时,会交给回调函数处理
SOCKET WSAAccept(
__in SOCKET s,
__out struct sockaddr* addr,
__in_out LPINT addrlen,
__in LPCONDITIONPROC lpfnCondition, //回调函数
__in DWORD dwCallbackData //回调数据
);
SOCKET WSAAccept(
__in SOCKET s,
__out struct sockaddr* addr,
__in_out LPINT addrlen,
__in LPCONDITIONPROC lpfnCondition, //回调函数
__in DWORD dwCallbackData //回调数据
);
#2
第一个问题,可以参看msdn,有一个相应回调函数的例子
第二个问题,是针对windows网络编程这本书的一个事件模型的例子来说的。
第二个问题是没有对连接数为0的情形做特殊处理,程序在连接数为0的时候CPU占用率为100%
这个意思是说,如果程序在连接数为0的情况下,没有任何要等待的网络事件,wait就会立刻返回,这个循环也会立即的,没有任何sleep的持续下去,占用所有的cpu时间
第二个问题,是针对windows网络编程这本书的一个事件模型的例子来说的。
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int ret, index;
WSANETWORKEVENTS NetworkEvents;
char szMessage[MSGSIZE];
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Receive message from client
ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
Cleanup(index);
}
else
{
szMessage[ret] = '\0';
send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
}
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
Cleanup(index);
}
}
return 0;
}
第二个问题是没有对连接数为0的情形做特殊处理,程序在连接数为0的时候CPU占用率为100%
这个意思是说,如果程序在连接数为0的情况下,没有任何要等待的网络事件,wait就会立刻返回,这个循环也会立即的,没有任何sleep的持续下去,占用所有的cpu时间
#3
那具体是如何解决100%呢? 而且我的是没有设置超时1000ms, 我的直接是WSA_INFINITE。我的会一直停在WSAWaitForMultipleEvents()中,没连接数时是没返回,加不加Sleep都是cpu100%的! 怎样搞定?
#4
你就把这个例子稍微修改下啊,我也发现了在连接数为0时,WSAWaitForMultipleEvents会立即返回,接着就是执行if (ret== **) {continue; } 。
#5
没有设置超时,是会立即返回,我也这样试过 了,但还是会cpu100%的,就会一直continue
#6
0连接时,g_iTotalConn = 0;
也即
WSAWaitForMultipleEvents(0, g_CliEventArr, FALSE, 1000, FALSE);
应该是一直循环ret == WSA_WAIT_FAILED
WSAGetLastError()=WSA_INVALID_PARAMETER
也即
WSAWaitForMultipleEvents(0, g_CliEventArr, FALSE, 1000, FALSE);
应该是一直循环ret == WSA_WAIT_FAILED
WSAGetLastError()=WSA_INVALID_PARAMETER
#7
但我的都是作为服务端,g_iTotalConn能是0吗/? 一开始都要有个socket作为监听的,所以g_iTotalConn这时都是1了
#8
你的意思是WSAWaitForMultipleEvents()一直没有返回,但此时cpu 100%
#9
感觉有点奇怪,你的事件对象自动传信的还是,手动传信类型的?
#10
对,就是这样
#11
WSAWaitForMultipleEvents 我的设置的是WSA_INFINITE
是自动传信的
#12
看代码吧
#include <winsock2.h>
#include <stdio.h>
#define PORT 5150
#define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID);
void Cleanup(int index);
int main()
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iaddrSize = sizeof(SOCKADDR_IN);
// Initialize Windows Socket library
WSAStartup(0x0202, &wsaData);
// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen
listen(sListen, 3);
// Create worker thread
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
// Associate socket with network event
g_CliSocketArr[g_iTotalConn] = sClient;
g_CliEventArr[g_iTotalConn] = WSACreateEvent();
WSAEventSelect(g_CliSocketArr[g_iTotalConn],
g_CliEventArr[g_iTotalConn],
FD_READ | FD_CLOSE);
g_iTotalConn++;
}
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int ret, index;
WSANETWORKEVENTS NetworkEvents;
char szMessage[MSGSIZE];
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Receive message from client
ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
Cleanup(index);
}
else
{
szMessage[ret] = '\0';
send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
}
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
Cleanup(index);
}
}
return 0;
}
void Cleanup(int index)
{
closesocket(g_CliSocketArr[index]);
WSACloseEvent(g_CliEventArr[index]);
if (index < g_iTotalConn - 1)
{
g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1];
g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1];
}
g_iTotalConn--;
}
accept之前 g_iTotalConn=0
一开始确是有个socket作为监听的,但没和g_CliEventArr关联起来,
事实上g_CliEventArr和g_CliSocketArr(accept返回的socket)对应的,
和那个监听socket无关的吧
#13
刚开始时g_iTotalConn=0
客户端连上后才g_iTotalConn++;
断开后又g_iTotalConn--;
这样就又可能出现g_iTotalConn等于0的情况
客户端连上后才g_iTotalConn++;
断开后又g_iTotalConn--;
这样就又可能出现g_iTotalConn等于0的情况
#14
marks
#1
1.WSAAccept,支持回调函数,在接收到connect请求时,会交给回调函数处理
SOCKET WSAAccept(
__in SOCKET s,
__out struct sockaddr* addr,
__in_out LPINT addrlen,
__in LPCONDITIONPROC lpfnCondition, //回调函数
__in DWORD dwCallbackData //回调数据
);
SOCKET WSAAccept(
__in SOCKET s,
__out struct sockaddr* addr,
__in_out LPINT addrlen,
__in LPCONDITIONPROC lpfnCondition, //回调函数
__in DWORD dwCallbackData //回调数据
);
#2
第一个问题,可以参看msdn,有一个相应回调函数的例子
第二个问题,是针对windows网络编程这本书的一个事件模型的例子来说的。
第二个问题是没有对连接数为0的情形做特殊处理,程序在连接数为0的时候CPU占用率为100%
这个意思是说,如果程序在连接数为0的情况下,没有任何要等待的网络事件,wait就会立刻返回,这个循环也会立即的,没有任何sleep的持续下去,占用所有的cpu时间
第二个问题,是针对windows网络编程这本书的一个事件模型的例子来说的。
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int ret, index;
WSANETWORKEVENTS NetworkEvents;
char szMessage[MSGSIZE];
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Receive message from client
ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
Cleanup(index);
}
else
{
szMessage[ret] = '\0';
send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
}
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
Cleanup(index);
}
}
return 0;
}
第二个问题是没有对连接数为0的情形做特殊处理,程序在连接数为0的时候CPU占用率为100%
这个意思是说,如果程序在连接数为0的情况下,没有任何要等待的网络事件,wait就会立刻返回,这个循环也会立即的,没有任何sleep的持续下去,占用所有的cpu时间
#3
那具体是如何解决100%呢? 而且我的是没有设置超时1000ms, 我的直接是WSA_INFINITE。我的会一直停在WSAWaitForMultipleEvents()中,没连接数时是没返回,加不加Sleep都是cpu100%的! 怎样搞定?
#4
你就把这个例子稍微修改下啊,我也发现了在连接数为0时,WSAWaitForMultipleEvents会立即返回,接着就是执行if (ret== **) {continue; } 。
#5
没有设置超时,是会立即返回,我也这样试过 了,但还是会cpu100%的,就会一直continue
#6
0连接时,g_iTotalConn = 0;
也即
WSAWaitForMultipleEvents(0, g_CliEventArr, FALSE, 1000, FALSE);
应该是一直循环ret == WSA_WAIT_FAILED
WSAGetLastError()=WSA_INVALID_PARAMETER
也即
WSAWaitForMultipleEvents(0, g_CliEventArr, FALSE, 1000, FALSE);
应该是一直循环ret == WSA_WAIT_FAILED
WSAGetLastError()=WSA_INVALID_PARAMETER
#7
但我的都是作为服务端,g_iTotalConn能是0吗/? 一开始都要有个socket作为监听的,所以g_iTotalConn这时都是1了
#8
你的意思是WSAWaitForMultipleEvents()一直没有返回,但此时cpu 100%
#9
感觉有点奇怪,你的事件对象自动传信的还是,手动传信类型的?
#10
对,就是这样
#11
WSAWaitForMultipleEvents 我的设置的是WSA_INFINITE
是自动传信的
#12
看代码吧
#include <winsock2.h>
#include <stdio.h>
#define PORT 5150
#define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID);
void Cleanup(int index);
int main()
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iaddrSize = sizeof(SOCKADDR_IN);
// Initialize Windows Socket library
WSAStartup(0x0202, &wsaData);
// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen
listen(sListen, 3);
// Create worker thread
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
// Associate socket with network event
g_CliSocketArr[g_iTotalConn] = sClient;
g_CliEventArr[g_iTotalConn] = WSACreateEvent();
WSAEventSelect(g_CliSocketArr[g_iTotalConn],
g_CliEventArr[g_iTotalConn],
FD_READ | FD_CLOSE);
g_iTotalConn++;
}
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int ret, index;
WSANETWORKEVENTS NetworkEvents;
char szMessage[MSGSIZE];
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Receive message from client
ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
Cleanup(index);
}
else
{
szMessage[ret] = '\0';
send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
}
}
if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
Cleanup(index);
}
}
return 0;
}
void Cleanup(int index)
{
closesocket(g_CliSocketArr[index]);
WSACloseEvent(g_CliEventArr[index]);
if (index < g_iTotalConn - 1)
{
g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1];
g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1];
}
g_iTotalConn--;
}
accept之前 g_iTotalConn=0
一开始确是有个socket作为监听的,但没和g_CliEventArr关联起来,
事实上g_CliEventArr和g_CliSocketArr(accept返回的socket)对应的,
和那个监听socket无关的吧
#13
刚开始时g_iTotalConn=0
客户端连上后才g_iTotalConn++;
断开后又g_iTotalConn--;
这样就又可能出现g_iTotalConn等于0的情况
客户端连上后才g_iTotalConn++;
断开后又g_iTotalConn--;
这样就又可能出现g_iTotalConn等于0的情况
#14
marks