完成端口如何循环发送数据给每一个客户端?

时间:2022-12-15 16:52:01
完成端口如何群发数据到所有客户SOCKET ,该如何操作
我用一个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);
}   
}   
}   

#2


群发跟单发一样的.就是遍历连接链表,单发.

#3


引用 2 楼 smwhotjay 的回复:
群发跟单发一样的.就是遍历连接链表,单发.

就是不会才问的!

#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


该回复于2011-10-24 10:07:29被版主删除

#8


俺会用数组来存放,反正俺也不在乎空间。

#9


accept时,保存所有连接。然后 遍历 发送。

#10


引用 9 楼 yynetsdk 的回复:
accept时,保存所有连接。然后 遍历 发送。


//我是先把客户新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


引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?

#12


EnterCriticalSection
//Your code
LeaveCriticalSection
引用 11 楼 zhouxicai 的回复:
引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?

#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


引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

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);
}   
}   
}   

#2


群发跟单发一样的.就是遍历连接链表,单发.

#3


引用 2 楼 smwhotjay 的回复:
群发跟单发一样的.就是遍历连接链表,单发.

就是不会才问的!

#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


该回复于2011-10-24 10:07:29被版主删除

#8


俺会用数组来存放,反正俺也不在乎空间。

#9


accept时,保存所有连接。然后 遍历 发送。

#10


引用 9 楼 yynetsdk 的回复:
accept时,保存所有连接。然后 遍历 发送。


//我是先把客户新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


引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?

#12


EnterCriticalSection
//Your code
LeaveCriticalSection
引用 11 楼 zhouxicai 的回复:
引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

为什么要用map?
听说最好还要用临界区,否则很容易出错,谁能贴出使用临界区的例子?

#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


引用 4 楼 jackson35296 的回复:
遍历链表发就可以,但是用链表来存放是不妥的,建议用map

map你考虑过插入时的时间消耗吗. 我测试过,map插入一个时,消耗大约10耗秒. - -! 完成端口如何循环发送数据给每一个客户端?