求SOCKET重叠模型结构定义示例代码.............
小猪的手把手教你玩转SOCKET模型之重叠文章看了,程序也下了感觉真的很不错,
但是猪哥的WSASEND部分没有示例,我调起来很困难,各位帮帮忙,最好有完整的示例代码,
谢过!
[解决办法]
WSASend和WSARecv的用法没有太大差别,你可以参考他的WSARecv代码
[解决办法]
- C/C++ code
#include "stdafx.h"WSAOVERLAPPED AcceptOverlapped[10];SOCKET s,c;int i;WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];WSABUF DataBuf; DWORD dwEventTotal, // 程序中事件的总数 dwRecvBytes, // 接收到的字符长度 Flags; // WSARecv的参数 void CALLBACK WorkRoutine(DWORD error,DWORD BytesTransferred,LPWSAOVERLAPPED Overlapped, DWORD InFlags){ DWORD SendBytes; DWORD RecvBytes; DWORD Flags; if(error != 0 || BytesTransferred == 0){ cout<<error<<endl; closesocket(c); return; } cout<<DataBuf.buf<<endl; return ;}DWORD WINAPI _AcceptProc(LPVOID lpParameter){ // c = WSASocket(AF_INET,SOCK_STREAM,0,NULL,NULL,WSA_FLAG_OVERLAPPED); SOCKET *s = (SOCKET*)lpParameter; char buffer[1024]; if(i == 10 ){ cout<<"客户连接已满"<<endl; shutdown(c,2); closesocket(c); i--; if(i == 0){ cout<<"以清空"<<endl; return 0; } return 0; } ZeroMemory(&buffer,sizeof(buffer)); DataBuf.buf = buffer; DataBuf.len = sizeof(buffer); while(1){ c = accept(*s,NULL,NULL); if(c == INVALID_SOCKET){ cout<<"Accept错误"<<endl; cout<<WSAGetLastError()<<endl; return 0; } ZeroMemory(&AcceptOverlapped[i],sizeof(AcceptOverlapped)); if(i == 0){ if( WSARecv(c,&DataBuf,1,&dwRecvBytes,&Flags,&AcceptOverlapped[i],WorkRoutine) == SOCKET_ERROR){ if(WSAGetLastError() != WSA_IO_PENDING){ cout<<"WSARecv failed with error"<<WSAGetLastError()<<endl; closesocket(c); WSACloseEvent(EventArray[dwEventTotal]); return 0; } } } i++; Sleep(500); } // CreateThread(NULL,0,_AcceptProc,s,0,NULL); return 0;}DWORD WINAPI _InterestEventProc(LPVOID lpParameter){ return 0;}int main(int argc, char* argv[]){ WSADATA wsaData; SOCKET s; sockaddr_in service,client; WORD Version = MAKEWORD(2,2); DWORD ThreadID; EventArray[dwEventTotal] = WSACreateEvent(); //lAcceptOverlapped.hEvent = EventArray[dwEventTotal]; dwEventTotal ++; WSAStartup(Version,&wsaData); s = WSASocket(AF_INET,SOCK_STREAM,0,NULL,NULL,WSA_FLAG_OVERLAPPED); if(s == INVALID_SOCKET){ cout<<"WSASocket错误"<<endl; cout<<WSAGetLastError()<<endl; getch(); WSACleanup(); return 0; } service.sin_addr.S_un.S_addr = INADDR_ANY; service.sin_family = AF_INET; service.sin_port = htons(5150); if( bind(s,(sockaddr*)&service,sizeof(sockaddr_in)) == SOCKET_ERROR){ cout<<"bind 错误"<<endl; cout<<WSAGetLastError()<<endl; getch(); WSACleanup(); return 0; } listen(s,10); CreateThread(NULL,0,_AcceptProc,&s,0,NULL); DWORD dwIndex = 0, dwBytesTransferred; while(1){ dwIndex = WSAWaitForMultipleEvents(dwEventTotal,EventArray,false,2000,true); if(dwIndex == WSA_WAIT_TIMEOUT){ cout<<"超时"<<endl; continue; } if(dwIndex == WAIT_IO_COMPLETION){ cout<<"IO完成"<<endl; break; } dwIndex = dwIndex - WSA_WAIT_EVENT_0; if(dwIndex == 0){ cout<<"连入一个用户"<<endl; continue; } WSAResetEvent(EventArray[dwIndex]); WSAGetOverlappedResult(s,&AcceptOverlapped[i],& dwBytesTransferred,false,&Flags); if(dwBytesTransferred == 0){ cout<<"数据流量0关闭"; closesocket(s); WSACloseEvent(EventArray[dwIndex]); // 关闭事件 return 0; } Sleep(500); } getch(); WSACloseEvent(EventArray[dwEventTotal]); closesocket(s); WSACleanup(); return 0;}
[解决办法]
希望有用,慢慢看
#include "../common/initsock.h" //初始化SOCKET环境,包括一个类,析构时调用WSACleanup
#include <Mswsock.h>
#include <stdio.h>
#include <windows.h>
CInitSock theSock; //实例化
#define BUFFER_SIZE 1024
typedef struct _SOCKET_OBJ
{
SOCKET s;// 套节字句柄
int nOutstandingOps;// 记录此套节字上的重叠I/O数量
LPFN_ACCEPTEX lpfnAcceptEx;// 扩展函数AcceptEx的指针(仅对监听套节字而言)
} SOCKET_OBJ, *PSOCKET_OBJ;
typedef struct _BUFFER_OBJ
{
OVERLAPPED ol;// 重叠结构
char *buff;// send/recv/AcceptEx所使用的缓冲区
int nLen;// buff的长度
PSOCKET_OBJ pSocket;// 此I/O所属的套节字对象
int nOperation;// 提交的操作类型
#define OP_ACCEPT1
#define OP_READ2
#define OP_WRITE3
SOCKET sAccept;// 用来保存AcceptEx接受的客户套节字(仅对监听套节字而言)
_BUFFER_OBJ *pNext;
} BUFFER_OBJ, *PBUFFER_OBJ;
HANDLE g_events[WSA_MAXIMUM_WAIT_EVENTS];// I/O事件句柄数组
int g_nBufferCount;// 上数组中有效句柄数量
PBUFFER_OBJ g_pBufferHead, g_pBufferTail;// 记录缓冲区对象组成的表的地址
// 申请套节字对象和释放套节字对象的函数
PSOCKET_OBJ GetSocketObj(SOCKET s)
{
PSOCKET_OBJ pSocket = (PSOCKET_OBJ)::GlobalAlloc(GPTR, sizeof(SOCKET_OBJ));
if(pSocket != NULL)
{
pSocket->s = s;
}
return pSocket;
}
void FreeSocketObj(PSOCKET_OBJ pSocket)
{
if(pSocket->s != INVALID_SOCKET)
::closesocket(pSocket->s);
::GlobalFree(pSocket);
}
PBUFFER_OBJ GetBufferObj(PSOCKET_OBJ pSocket, ULONG nLen)
{
if(g_nBufferCount > WSA_MAXIMUM_WAIT_EVENTS - 1)
return NULL;
PBUFFER_OBJ pBuffer = (PBUFFER_OBJ)::GlobalAlloc(GPTR, sizeof(BUFFER_OBJ));
if(pBuffer != NULL)
{
pBuffer->buff = (char*)::GlobalAlloc(GPTR, nLen);
pBuffer->ol.hEvent = ::WSACreateEvent();
pBuffer->pSocket = pSocket;
pBuffer->sAccept = INVALID_SOCKET;
// 将新的BUFFER_OBJ添加到列表中
if(g_pBufferHead == NULL)
{
g_pBufferHead = g_pBufferTail = pBuffer;
}
else
{
g_pBufferTail->pNext = pBuffer;
g_pBufferTail = pBuffer;
}
g_events[++ g_nBufferCount] = pBuffer->ol.hEvent;
}
return pBuffer;
}
void FreeBufferObj(PBUFFER_OBJ pBuffer)
{
// 从列表中移除BUFFER_OBJ对象
PBUFFER_OBJ pTest = g_pBufferHead;
BOOL bFind = FALSE;
if(pTest == pBuffer)
{
g_pBufferHead = g_pBufferTail = NULL;
bFind = TRUE;
}
else
{
while(pTest != NULL && pTest->pNext != pBuffer)
pTest = pTest->pNext;
if(pTest != NULL)
{
pTest->pNext = pBuffer->pNext;
if(pTest->pNext == NULL)
g_pBufferTail = pTest;
bFind = TRUE;
}
}
// 释放它占用的内存空间
if(bFind)
{
g_nBufferCount --;
::CloseHandle(pBuffer->ol.hEvent);
::GlobalFree(pBuffer->buff);
::GlobalFree(pBuffer);
}
}
PBUFFER_OBJ FindBufferObj(HANDLE hEvent)
{
PBUFFER_OBJ pBuffer = g_pBufferHead;
while(pBuffer != NULL)
{
if(pBuffer->ol.hEvent == hEvent)
break;
pBuffer = pBuffer->pNext;
}
return pBuffer;
}
void RebuildArray()
{
PBUFFER_OBJ pBuffer = g_pBufferHead;
int i = 1;
while(pBuffer != NULL)
{
g_events[i++] = pBuffer->ol.hEvent;
pBuffer = pBuffer->pNext;
}
}
BOOL PostAccept(PBUFFER_OBJ pBuffer)
{
PSOCKET_OBJ pSocket = pBuffer->pSocket;
if(pSocket->lpfnAcceptEx != NULL)
{
// 设置I/O类型,增加套节字上的重叠I/O计数
pBuffer->nOperation = OP_ACCEPT;
pSocket->nOutstandingOps ++;
// 投递此重叠I/O
DWORD dwBytes;
pBuffer->sAccept =
::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
BOOL b = pSocket->lpfnAcceptEx(pSocket->s,
pBuffer->sAccept,
pBuffer->buff,
BUFFER_SIZE - ((sizeof(sockaddr_in) + 16) * 2),
sizeof(sockaddr_in) + 16,
sizeof(sockaddr_in) + 16,
&dwBytes,
&pBuffer->ol);
if(!b)
{
if(::WSAGetLastError() != WSA_IO_PENDING)
return FALSE;
}
return TRUE;
}
return FALSE;
};
BOOL PostRecv(PBUFFER_OBJ pBuffer)
{
// 设置I/O类型,增加套节字上的重叠I/O计数
pBuffer->nOperation = OP_READ;
pBuffer->pSocket->nOutstandingOps ++;
// 投递此重叠I/O
DWORD dwBytes;
DWORD dwFlags = 0;
WSABUF buf;
buf.buf = pBuffer->buff;
buf.len = pBuffer->nLen;
if(::WSARecv(pBuffer->pSocket->s, &buf, 1, &dwBytes, &dwFlags, &pBuffer->ol, NULL) != NO_ERROR)
{
if(::WSAGetLastError() != WSA_IO_PENDING)
return FALSE;
}
return TRUE;
}