我做了一个UDP的服务器采用完成端口的方式,我在wsarecv后可以通过GetQueuedCompletionStatus得到一个完成事件,这时我对得到的数据进行处理,但是我想用通过接受的内容将数据wsasend到发送方,就会出现10057错误,主要是由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。我想问的是如何通过完成端口方式可以得到发送的一些信息:比如发送方的在服务器的端口信息。
解决方案 »
- 使用CSerialPort类 做通讯,关闭的时候会自动又弹出一个实例
- C语言 效率的典范还是肮脏的技巧?你有精巧的设计也拿来晒晒。
- 关于 sprint 、int超出范围
- 如何 IE 增加类似迅雷的 菜单,不是工具栏
- 调用DLL出错,提示 unhandled exception in md5exe.exe (MD5DLL.DLL): 0xC0000005: Access Violation
- 请教如何将CString付给CTime 变量
- 请问怎么样清除,在视图里的绘画
- 一个简单的问题,怎样使视图里的文字在窗口改变时不被刷掉?
- 能不能用ADO通过网络访问远程的SQL SERVER?有例子最好。
- file.Open(filename,CFile::modeCreate|CFile::typeBinary|CFile::modeWrite)
- 可以给我CVS版本控制方面的软件吗?
- 编程自动在Gmail的邮件编辑框中插入图片的问题
WSARecvFrom当中就有对方的地址和端口,此时WSASendTo就可以使用之。
{
::InitializeCriticalSection(&m_cSection);
m_bTcpType = bTcp;
m_bUdpType = bUdp;
m_iTcpPort = iTcpPort;
m_iUdpPort = iUdpPort;
CString strError;
if ( m_bUdpType )
{
m_sUdpSever = CreateSever(UDP);
if ( m_sUdpSever == INVALID_SOCKET )
{
return FALSE;
} m_hUdpCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if ( m_hUdpCompletionPort == NULL )
{
m_dwError = GetLastError();
strError.Format("%d", m_dwError);
CloseHandle(m_hTcpCompletionPort);
AfxMessageBox("Create UDP IO Completion port Fail, error:" + strError);
return FALSE;
}
char szName[_MAX_PATH];
CString str;
int err = gethostname(szName, _MAX_PATH);
if ( err == SOCKET_ERROR )
{
str.Format("%d", WSAGetLastError());
}
HOSTENT *pHostent = gethostbyname(szName);
if ( pHostent == NULL )
{
AfxMessageBox("Communication gethostbyname error");
return FALSE;
}
in_addr addr;
memcpy(&addr, pHostent->h_addr_list[0], sizeof(in_addr));
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
for ( int i = 0; i < 1/*sysInfo.dwNumberOfProcessors*2+2*/; i++)
{
DWORD WorkerThreadForUdpId;
HANDLE hWorkerThreadForUdp = CreateThread(NULL,
0,
&WorkerForUDPProc,
this,
0,
&WorkerThreadForUdpId);
if ( hWorkerThreadForUdp == NULL )
{
m_dwError = GetLastError();
strError.Format("%d", m_dwError);
CloseHandle(hWorkerThreadForUdp);
AfxMessageBox("Create WorkerThreadForUdp Thread Fail, error:" + strError);
return FALSE;
}
CloseHandle(hWorkerThreadForUdp);
} LPPERHANDLEDATA PerHandleDataForUdp = (LPPERHANDLEDATA)GlobalAlloc(GPTR, sizeof(PERHANDLEDATA));
SOCKADDR_IN addrFrom;
int iSize = sizeof(addrFrom);
CreateIoCompletionPort((HANDLE)m_sUdpSever,
m_hUdpCompletionPort,
(DWORD)&addrFrom,
0);
DWORD RecvBytes, Flag = 0;
LPPERIOHANDLEDATA PerIoHandleDataForUdp = (LPPERIOHANDLEDATA)GlobalAlloc(GPTR, sizeof(PERIOHANDLEDATA));
memset(&(PerIoHandleDataForUdp->Overlap), 0, sizeof(OVERLAPPED));
PerIoHandleDataForUdp->RecvDataBuf.buf = PerIoHandleDataForUdp->RecvBuf;
PerIoHandleDataForUdp->RecvDataBuf.len = POCKET_DEFAULT_SIZE;
PerIoHandleDataForUdp->iType = RECV_DATA;
err = WSARecvFrom(m_sUdpSever,
&(PerIoHandleDataForUdp->RecvDataBuf),
1,
&RecvBytes,
&Flag,
(sockaddr*)&addrFrom,
&iSize,
&(PerIoHandleDataForUdp->Overlap),
NULL);
if ( err == SOCKET_ERROR )
{
str.Format("%d", WSAGetLastError());
}
}
return TRUE;
}
DWORD WINAPI WorkerForUDPProc(LPVOID lParam)
{
int err;
CString strErr;
CCommunication* pCommunication = (CCommunication*)lParam;
LPPERHANDLEDATA PerHandleData;
SOCKADDR_IN addr;
LPPERIOHANDLEDATA PerIoHandleData;
DWORD dwRecvByte = 0;
while (TRUE)
{
BOOL bSuccess = GetQueuedCompletionStatus(pCommunication->GetUdpCompletionPort(),
&dwRecvByte,
(LPDWORD)&addr,
(LPOVERLAPPED*)&PerIoHandleData,
INFINITE);
if ( dwRecvByte == -1 && PerHandleData == NULL )
{
return 1L;
} if ( dwRecvByte != 0 && PerIoHandleData->iType == RECV_DATA )
{
pCommunication->DealDataFromUdpComletionPort(PerHandleData, PerIoHandleData, dwRecvByte);
DWORD dwFlag = 0;
memset(PerIoHandleData->SendBuf, 0, POCKET_DEFAULT_SIZE);
memcpy(PerIoHandleData->SendBuf, PerIoHandleData->RecvBuf, POCKET_DEFAULT_SIZE);
PerIoHandleData->iType = SEND_DATA;
PerIoHandleData->SendDataBuf.buf = PerIoHandleData->SendBuf;
PerIoHandleData->SendDataBuf.len = PerIoHandleData->RecvDataBuf.len;
memset(PerIoHandleData->RecvBuf, 0, POCKET_DEFAULT_SIZE);
memset(&PerIoHandleData->Overlap, 0, sizeof(OVERLAPPED));
err = WSASendTo(pCommunication->GetUdpSeverSocket(),
&(PerIoHandleData->SendDataBuf),
1,
&dwRecvByte,
dwFlag,
(sockaddr*)&addrFrom,
sizeof(sockaddr),
&(PerIoHandleData->Overlap),
NULL);
if ( err == SOCKET_ERROR )
{
strErr.Format("%d", WSAGetLastError());
}
}
else if ( dwRecvByte == 0 && ((PerIoHandleData->iType == RECV_DATA) || (PerIoHandleData->iType == SEND_DATA)) )
{
//delete client
}
}
return 1L;
}
我是这样写的,不知道哪里错掉了。
看到你贴出来的代码,我感觉前面我说的全是废话
为什么是废话???
然后,WSARecvFrom当中的地址和地址长度,都是出参,需要交给系统去改写,那么这个地址,就需要动态分配,否则系统会写入到一个野指针当中,后果难以想象。同样的,既然使用的是一个动态分配的内存空间,那么这个指针就需要保存,更何况后面通讯的时候还需要用到,最好的办法是放到Overlapped的扩展结构当中去。