我用一个LIST存储新连接的SOCKET,然后用遍历iter但是不能正常收发数据。
没用LIST以前,服务器能收到所有信息,客户端只能收到自己发到服务器 的信息,并不能收到别的客户端信息。
15 个解决方案
#1
以下是删掉了遍历iter的代码:
#define PORT 55555
#define DATA_BUFSIZE 8192
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
struct RecvDate
{
float float1[3];
char Str[128];
};
RecvDate RecvDate2;
list<SOCKET> accept_socket_number;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
void IOCPmain(void)
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
unsigned int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
if ( ( Ret = WSAStartup(0x0202, &wsaData) ) != 0 )
{
printf( "WSAStartup failed with error %d\n", Ret );
return;
} printf( "WSAStartup the end ...\n" );
// Setup an I/O completion port.
if ( ( CompletionPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, 0, 0 ) ) == NULL )
{
printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError() );
return;
} printf( "CreateIoCompletionPort the end ...\n" );
GetSystemInfo(&SystemInfo); // 系统有几个*处理器 ;
// 基于系统处理器数量创建工作者线程, 为每个处理器创建两个工作者线程。 ;
printf("CPU number : %d ...\n",SystemInfo.dwNumberOfProcessors);
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// 创建一个服务器工作者线程并通过完成端口连接它。;
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
} printf_s("CreateThread %d the end ... Enter Thread %d ...\n",i+1,i+1);
// cout<<"CreateThread "<<i+1 <<" the end ... Enter Thread " <<i+1 <<" ...\n";
CloseHandle(ThreadHandle); // Close the thread handle
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return;
} printf("WSASocket the end ...\n");
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
} printf("Bind the end ...\n");
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
} printf("Listen the end ...\nEnter the loop ...\n");
while(TRUE)
{ // 接受连接并分配该完成端口。;
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
} printf("WSAAccept Loop ...\n");
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the accepted socket with the original completion port.
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD) PerHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return;
} printf("Set CreateIoCompletionPort end...\n");
// Create per I/O socket information structure to associate with the WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) ) ) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE; //初始化长度 ;
PerIoData->DataBuf.buf = PerIoData->Buffer; //初始化大小 ;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中 ;
}
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("\nGetQueuedCompletionStatus failed with error %d\n", GetLastError());
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
else
{
PerIoData->BytesRECV = 0;
// Now that there are no more bytes to send post another WSARecv() request.
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
//接收 ;
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("\n wsarecv() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Receive date success ...");
char inbuff[1024];
RecvDate2=*(RecvDate*)(PerIoData->Buffer) ;
sprintf_s( inbuff , " S1:%s F0:%f F1:%f F2:%f " , RecvDate2.Str ,
RecvDate2.float1[0] , RecvDate2.float1[1] , RecvDate2.float1[2] ) ;
printf("\n Receive from the client of coordinates ...\n%s ", inbuff);
}
}
}
#define PORT 55555
#define DATA_BUFSIZE 8192
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
struct RecvDate
{
float float1[3];
char Str[128];
};
RecvDate RecvDate2;
list<SOCKET> accept_socket_number;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
void IOCPmain(void)
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
unsigned int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
if ( ( Ret = WSAStartup(0x0202, &wsaData) ) != 0 )
{
printf( "WSAStartup failed with error %d\n", Ret );
return;
} printf( "WSAStartup the end ...\n" );
// Setup an I/O completion port.
if ( ( CompletionPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, 0, 0 ) ) == NULL )
{
printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError() );
return;
} printf( "CreateIoCompletionPort the end ...\n" );
GetSystemInfo(&SystemInfo); // 系统有几个*处理器 ;
// 基于系统处理器数量创建工作者线程, 为每个处理器创建两个工作者线程。 ;
printf("CPU number : %d ...\n",SystemInfo.dwNumberOfProcessors);
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// 创建一个服务器工作者线程并通过完成端口连接它。;
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
} printf_s("CreateThread %d the end ... Enter Thread %d ...\n",i+1,i+1);
// cout<<"CreateThread "<<i+1 <<" the end ... Enter Thread " <<i+1 <<" ...\n";
CloseHandle(ThreadHandle); // Close the thread handle
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return;
} printf("WSASocket the end ...\n");
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
} printf("Bind the end ...\n");
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
} printf("Listen the end ...\nEnter the loop ...\n");
while(TRUE)
{ // 接受连接并分配该完成端口。;
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
} printf("WSAAccept Loop ...\n");
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the accepted socket with the original completion port.
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD) PerHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return;
} printf("Set CreateIoCompletionPort end...\n");
// Create per I/O socket information structure to associate with the WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) ) ) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE; //初始化长度 ;
PerIoData->DataBuf.buf = PerIoData->Buffer; //初始化大小 ;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中 ;
}
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("\nGetQueuedCompletionStatus failed with error %d\n", GetLastError());
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
else
{
PerIoData->BytesRECV = 0;
// Now that there are no more bytes to send post another WSARecv() request.
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
//接收 ;
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("\n wsarecv() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Receive date success ...");
char inbuff[1024];
RecvDate2=*(RecvDate*)(PerIoData->Buffer) ;
sprintf_s( inbuff , " S1:%s F0:%f F1:%f F2:%f " , RecvDate2.Str ,
RecvDate2.float1[0] , RecvDate2.float1[1] , RecvDate2.float1[2] ) ;
printf("\n Receive from the client of coordinates ...\n%s ", inbuff);
}
}
}
#2
群发跟单发一样的.就是遍历连接链表,单发.
#3
就是不会才问的!
#4
遍历链表发就可以,但是用链表来存放是不妥的,建议用map
#5
哪位大神知道啊?
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
#6
这么长代码,一看就晕了……友情帮顶~~
#7
#8
俺会用数组来存放,反正俺也不在乎空间。
#9
accept时,保存所有连接。然后 遍历 发送。
#10
//我是先把客户新SOCKET添加到LIST中,
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中
//然后,遍历LIST,
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
//但是发送时,我该如何将LIST中的SOCKET用WSASend函数转发出去了?
(WSASend(PerHandleData->Socket,... ...
#11
为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?
#12
EnterCriticalSection
//Your code
LeaveCriticalSection
//Your code
LeaveCriticalSection
#13
强烈要求回复10楼的问题。。
#14
我是用下面的办法发送,编译没问题,但是运行时,有错,数据不能发出。。我该怎么做?
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
if (WSASend((SOCKET)&iter, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
#15
map你考虑过插入时的时间消耗吗. 我测试过,map插入一个时,消耗大约10耗秒. - -!
#1
以下是删掉了遍历iter的代码:
#define PORT 55555
#define DATA_BUFSIZE 8192
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
struct RecvDate
{
float float1[3];
char Str[128];
};
RecvDate RecvDate2;
list<SOCKET> accept_socket_number;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
void IOCPmain(void)
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
unsigned int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
if ( ( Ret = WSAStartup(0x0202, &wsaData) ) != 0 )
{
printf( "WSAStartup failed with error %d\n", Ret );
return;
} printf( "WSAStartup the end ...\n" );
// Setup an I/O completion port.
if ( ( CompletionPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, 0, 0 ) ) == NULL )
{
printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError() );
return;
} printf( "CreateIoCompletionPort the end ...\n" );
GetSystemInfo(&SystemInfo); // 系统有几个*处理器 ;
// 基于系统处理器数量创建工作者线程, 为每个处理器创建两个工作者线程。 ;
printf("CPU number : %d ...\n",SystemInfo.dwNumberOfProcessors);
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// 创建一个服务器工作者线程并通过完成端口连接它。;
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
} printf_s("CreateThread %d the end ... Enter Thread %d ...\n",i+1,i+1);
// cout<<"CreateThread "<<i+1 <<" the end ... Enter Thread " <<i+1 <<" ...\n";
CloseHandle(ThreadHandle); // Close the thread handle
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return;
} printf("WSASocket the end ...\n");
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
} printf("Bind the end ...\n");
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
} printf("Listen the end ...\nEnter the loop ...\n");
while(TRUE)
{ // 接受连接并分配该完成端口。;
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
} printf("WSAAccept Loop ...\n");
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the accepted socket with the original completion port.
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD) PerHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return;
} printf("Set CreateIoCompletionPort end...\n");
// Create per I/O socket information structure to associate with the WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) ) ) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE; //初始化长度 ;
PerIoData->DataBuf.buf = PerIoData->Buffer; //初始化大小 ;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中 ;
}
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("\nGetQueuedCompletionStatus failed with error %d\n", GetLastError());
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
else
{
PerIoData->BytesRECV = 0;
// Now that there are no more bytes to send post another WSARecv() request.
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
//接收 ;
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("\n wsarecv() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Receive date success ...");
char inbuff[1024];
RecvDate2=*(RecvDate*)(PerIoData->Buffer) ;
sprintf_s( inbuff , " S1:%s F0:%f F1:%f F2:%f " , RecvDate2.Str ,
RecvDate2.float1[0] , RecvDate2.float1[1] , RecvDate2.float1[2] ) ;
printf("\n Receive from the client of coordinates ...\n%s ", inbuff);
}
}
}
#define PORT 55555
#define DATA_BUFSIZE 8192
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
struct RecvDate
{
float float1[3];
char Str[128];
};
RecvDate RecvDate2;
list<SOCKET> accept_socket_number;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
void IOCPmain(void)
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
unsigned int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
if ( ( Ret = WSAStartup(0x0202, &wsaData) ) != 0 )
{
printf( "WSAStartup failed with error %d\n", Ret );
return;
} printf( "WSAStartup the end ...\n" );
// Setup an I/O completion port.
if ( ( CompletionPort = CreateIoCompletionPort ( INVALID_HANDLE_VALUE, NULL, 0, 0 ) ) == NULL )
{
printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError() );
return;
} printf( "CreateIoCompletionPort the end ...\n" );
GetSystemInfo(&SystemInfo); // 系统有几个*处理器 ;
// 基于系统处理器数量创建工作者线程, 为每个处理器创建两个工作者线程。 ;
printf("CPU number : %d ...\n",SystemInfo.dwNumberOfProcessors);
for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++)
{
HANDLE ThreadHandle;
// 创建一个服务器工作者线程并通过完成端口连接它。;
if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
} printf_s("CreateThread %d the end ... Enter Thread %d ...\n",i+1,i+1);
// cout<<"CreateThread "<<i+1 <<" the end ... Enter Thread " <<i+1 <<" ...\n";
CloseHandle(ThreadHandle); // Close the thread handle
}
// Create a listening socket
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return;
} printf("WSASocket the end ...\n");
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(PORT);
if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return;
} printf("Bind the end ...\n");
// Prepare socket for listening
if (listen(Listen, 5) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return;
} printf("Listen the end ...\nEnter the loop ...\n");
while(TRUE)
{ // 接受连接并分配该完成端口。;
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return;
} printf("WSAAccept Loop ...\n");
// Create a socket information structure to associate with the socket
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
// Associate the accepted socket with the original completion port.
printf("Socket number %d connected\n", Accept);
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD) PerHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
return;
} printf("Set CreateIoCompletionPort end...\n");
// Create per I/O socket information structure to associate with the WSARecv call below.
if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA) ) ) == NULL)
{
printf("GlobalAlloc() failed with error %d\n", GetLastError());
return;
}
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->BytesSEND = 0;
PerIoData->BytesRECV = 0;
PerIoData->DataBuf.len = DATA_BUFSIZE; //初始化长度 ;
PerIoData->DataBuf.buf = PerIoData->Buffer; //初始化大小 ;
Flags = 0;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中 ;
}
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = (HANDLE) CompletionPortID;
DWORD BytesTransferred;
// LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
while(TRUE)
{
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)
{
printf("\nGetQueuedCompletionStatus failed with error %d\n", GetLastError());
return 0;
}
// First check to see if an error has occured on the socket and if so
// then close the socket and cleanup the SOCKET_INFORMATION structure associated with the socket.
if (BytesTransferred == 0)
{
printf("Closing socket %d\n", PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
// Check to see if the BytesRECV field equals zero. If this is so, then
// this means a WSARecv call just completed so update the BytesRECV field
// with the BytesTransferred value from the completed WSARecv() call.
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
PerIoData->BytesSEND = 0;
}
else
{
PerIoData->BytesSEND += BytesTransferred;
}
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
else
{
PerIoData->BytesRECV = 0;
// Now that there are no more bytes to send post another WSARecv() request.
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
//接收 ;
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("\n wsarecv() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Receive date success ...");
char inbuff[1024];
RecvDate2=*(RecvDate*)(PerIoData->Buffer) ;
sprintf_s( inbuff , " S1:%s F0:%f F1:%f F2:%f " , RecvDate2.Str ,
RecvDate2.float1[0] , RecvDate2.float1[1] , RecvDate2.float1[2] ) ;
printf("\n Receive from the client of coordinates ...\n%s ", inbuff);
}
}
}
#2
群发跟单发一样的.就是遍历连接链表,单发.
#3
就是不会才问的!
#4
遍历链表发就可以,但是用链表来存放是不妥的,建议用map
#5
哪位大神知道啊?
//从头开始遍历 ;
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
if (PerIoData->BytesRECV > PerIoData->BytesSEND)
{ // Post another WSASend() request.
// Since WSASend() is not gauranteed to send all of the bytes requested,
// continue posting WSASend() calls until all received bytes are sent.
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->Buffer + PerIoData->BytesSEND;
PerIoData->DataBuf.len = PerIoData->BytesRECV - PerIoData->BytesSEND;
//发送 ;
if (WSASend(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
#6
这么长代码,一看就晕了……友情帮顶~~
#7
#8
俺会用数组来存放,反正俺也不在乎空间。
#9
accept时,保存所有连接。然后 遍历 发送。
#10
//我是先把客户新SOCKET添加到LIST中,
accept_socket_number.push_back(Accept) ;//添加新客户到LIST中
//然后,遍历LIST,
list<SOCKET>::iterator iter ; int i = 1 ;
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
}
//但是发送时,我该如何将LIST中的SOCKET用WSASend函数转发出去了?
(WSASend(PerHandleData->Socket,... ...
#11
为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?
#12
EnterCriticalSection
//Your code
LeaveCriticalSection
//Your code
LeaveCriticalSection
#13
强烈要求回复10楼的问题。。
#14
我是用下面的办法发送,编译没问题,但是运行时,有错,数据不能发出。。我该怎么做?
for( iter = accept_socket_number.begin() ; iter != accept_socket_number.end() ; iter++ )
{
printf("\n iter %d %d ...",i,iter); i ++ ;
if (WSASend((SOCKET)&iter, &(PerIoData->DataBuf), 1, &SendBytes, 0, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
} printf("\n Send data success ... ");
}
#15
map你考虑过插入时的时间消耗吗. 我测试过,map插入一个时,消耗大约10耗秒. - -!