在看别人的代码,这部分以前是串口传输的,现在改成socket传输了
主界面的OnTimer函数会执行下面的ExcuteCommand函数,
BOOL CComWnd::ExcuteCommand(COneCommand *pCmd) {
m_bWriting=TRUE;//m_bWriting是用来判断读写是否完成的,在WriteThread中,如果sennd完毕,则m_bWriting=TRUE
AfxBeginThread(WriteThread,this,THREAD_PRIORITY_NORMAL);
while(m_bWriting)
Sleep(1);
if(m_bComError)
return FALSE;
AfxBeginThread(ReadThread,this,THREAD_PRIORITY_NORMAL);
}
上面的代码中,while(m_bWriting)的循环条件能保证主线程一直等待,WriteThread中完全把消息发送完,但是ReadThread就没有保证能完全读完消息之后才允许退出,
比如这种情况,WriteThread正常执行,对端收到消息后会立刻回复相应消息, 回应的消息由ReadThread接收(其实ReadThread就是执行了一下recv函数),如果消息传输有延迟, ReadThread函数执行完的时候,消息还没有传输到服务端,这样的话recv岂不就没读到数据?
(1)这里的代码能避免上述情况吗?
(2)如果想实现一个安全,稳定的服务端收发消息的代码(MFC界面程序,消息量不大,最长的消息是4000字节左右),我读过的代码比较少, 不知道其他socket服务端进程是怎么实现的,能不能发个代码参考? 邮箱[email protected] ,谢谢了最后贴一下ReadThread的代码:UINT ReadThread(LPVOID param) {
CComWnd *pComWnd=(CComWnd *)param;
int ReadResults=0;
BOOL Ready=FALSE;
BYTE* buffer=(BYTE*)malloc(sizeof(BYTE)*5036);
ReadResults=recv(socket,buffer,5036,0)
int i=0;
while(!Ready) {
if(AddToReceiveBuffer(*(buffer+i))) {
Ready=TRUE;
}
i++;
}
free(buffer);
return 0;
}
主界面的OnTimer函数会执行下面的ExcuteCommand函数,
BOOL CComWnd::ExcuteCommand(COneCommand *pCmd) {
m_bWriting=TRUE;//m_bWriting是用来判断读写是否完成的,在WriteThread中,如果sennd完毕,则m_bWriting=TRUE
AfxBeginThread(WriteThread,this,THREAD_PRIORITY_NORMAL);
while(m_bWriting)
Sleep(1);
if(m_bComError)
return FALSE;
AfxBeginThread(ReadThread,this,THREAD_PRIORITY_NORMAL);
}
上面的代码中,while(m_bWriting)的循环条件能保证主线程一直等待,WriteThread中完全把消息发送完,但是ReadThread就没有保证能完全读完消息之后才允许退出,
比如这种情况,WriteThread正常执行,对端收到消息后会立刻回复相应消息, 回应的消息由ReadThread接收(其实ReadThread就是执行了一下recv函数),如果消息传输有延迟, ReadThread函数执行完的时候,消息还没有传输到服务端,这样的话recv岂不就没读到数据?
(1)这里的代码能避免上述情况吗?
(2)如果想实现一个安全,稳定的服务端收发消息的代码(MFC界面程序,消息量不大,最长的消息是4000字节左右),我读过的代码比较少, 不知道其他socket服务端进程是怎么实现的,能不能发个代码参考? 邮箱[email protected] ,谢谢了最后贴一下ReadThread的代码:UINT ReadThread(LPVOID param) {
CComWnd *pComWnd=(CComWnd *)param;
int ReadResults=0;
BOOL Ready=FALSE;
BYTE* buffer=(BYTE*)malloc(sizeof(BYTE)*5036);
ReadResults=recv(socket,buffer,5036,0)
int i=0;
while(!Ready) {
if(AddToReceiveBuffer(*(buffer+i))) {
Ready=TRUE;
}
i++;
}
free(buffer);
return 0;
}
LS能不能详细提示下? 3ks!
UINT __cdecl Listening( LPVOID pParam )
{
CMainFrame* pMainFram = (CMainFrame*)pParam; pMainFram->hDataCopyEvent = CreateEvent(NULL, true, false, NULL);
int err;
CString csInfo;
// Create a servernetwork object
pMainFram->m_ServerNetwork.InitiateNetwork();
do
{
// Listening for incoming data
pMainFram->OutputDebugInfo(L"Listening...");
err = pMainFram->m_ServerNetwork.RecvDatagram(pMainFram->m_cBuffer, 1024, pMainFram->m_SenderAddr);
csInfo.Format(L"In coming data.Error code:0x%x", err);
pMainFram->OutputDebugInfo(csInfo);
csInfo.Format(L"Client ip:%d.%d.%d.%d port:%d",
pMainFram-> m_SenderAddr.sin_addr.S_un.S_un_b.s_b1,
pMainFram-> m_SenderAddr.sin_addr.S_un.S_un_b.s_b2,
pMainFram-> m_SenderAddr.sin_addr.S_un.S_un_b.s_b3,
pMainFram-> m_SenderAddr.sin_addr.S_un.S_un_b.s_b4,
ntohs(pMainFram-> m_SenderAddr.sin_port));
pMainFram->OutputDebugInfo(csInfo); // Check hListenTheadEvent state for exit event
if(WaitForSingleObject(pMainFram->hListenTheadEvent, 0) == WAIT_OBJECT_0)
{
// Signaled
ResetEvent(pMainFram->hListenTheadEvent);
pMainFram->OutputDebugInfo(L"Listening thread exit.");
pMainFram->pListenThrad = NULL;
return 1;
} // Pass cmainfram to dataprocess thread
AfxBeginThread(DataProcess, pParam);
// Wait until copy complete
WaitForSingleObject(pMainFram->hDataCopyEvent, INFINITE);
ResetEvent(pMainFram->hDataCopyEvent);
}
while(err); pMainFram->pListenThrad = NULL;
return 0;
}#include "StdAfx.h"
#include "ServerNetwork.h"
#define GFXMONITORPORT 5013CServerNetwork::CServerNetwork(void)
{
}
CServerNetwork::~CServerNetwork(void)
{
}int CServerNetwork::InitiateNetwork()
{
//Initiate use of the winscok all
WORD wVersionRequested;
WSADATA wsaData;
int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData);
if(err != 0)
{
err = WSAGetLastError();
WSACleanup();
return err;
} /*Confirm that the WinSock Dll supports 2.2*/ if(LOBYTE(wsaData.wVersion) != 2 ||
HIBYTE(wsaData.wVersion) != 2)
{
err = WSAGetLastError();
WSACleanup();
return err;
} /*The WinSock Dll is acceptable, proceed */ //Create a server socket
m_wsaServerSocket = WSASocket(AF_INET,
SOCK_DGRAM,
IPPROTO_UDP,
NULL,
0,
WSA_FLAG_OVERLAPPED); if(m_wsaServerSocket == INVALID_SOCKET)
{
err = WSAGetLastError();
WSACleanup();
return err;
} //Craete a receive addr
SOCKADDR_IN ReceiverAddr;
// Set up a SOCKADDR_IN structure that will tell bind that we
// want to receive datagrams from all interfaces using port
// 5150. ReceiverAddr.sin_family = AF_INET;
ReceiverAddr.sin_port = htons(GFXMONITORPORT);
ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Associate the address information with the socket using bind. bind(m_wsaServerSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr));
return 0;
}int CServerNetwork::RecvDatagram(CHAR* cBuffer, ULONG ulLength, sockaddr_in& SenderAddr)
{
DWORD BytesRecv = 0, Flags = 0;
int SenderAddrSize = sizeof(SenderAddr), err = 0; //Create a wsabuf to hold the recv buffer
WSABUF DataBuf;
DataBuf.buf = cBuffer;
DataBuf.len = ulLength; //Crate an event handle and setup a overlapped structure
WSAOVERLAPPED RecvOverlapped;
RecvOverlapped.hEvent = WSACreateEvent(); err = WSARecvFrom(m_wsaServerSocket,
&DataBuf,
1,
&BytesRecv,
&Flags,
(SOCKADDR *) &SenderAddr,
&SenderAddrSize,
&RecvOverlapped,
NULL); if(err == SOCKET_ERROR)
{
err = WSAGetLastError();
if(err != WSA_IO_PENDING)
{
return err;
}
}
if(RecvOverlapped.hEvent == NULL)
{
return WSAGetLastError();
} err = WSAGetOverlappedResult(m_wsaServerSocket,
&RecvOverlapped,
&BytesRecv,
TRUE,
&Flags);
if(err != TRUE)
{
return WSAGetLastError();
} return err;
}
int CServerNetwork::SendDatagram(CHAR* cBuffer, ULONG ulLength, SOCKADDR_IN RecieverAddress)
{
DWORD BytesSend = 0, Flags = 0;
int RecieverAddressSize = sizeof(RecieverAddress), err = 0; //Create a wsabuf to hold the recv buffer
WSABUF DataBuf;
DataBuf.buf = cBuffer;
DataBuf.len = ulLength; //Crate an event handle and setup a overlapped structure
WSAOVERLAPPED SendOverlapped;
SendOverlapped.hEvent = WSACreateEvent(); err = WSASendTo(m_wsaServerSocket,
&DataBuf,
1,
&BytesSend,
Flags,
(SOCKADDR *)&RecieverAddress,
RecieverAddressSize,
&SendOverlapped,
NULL); if(err == SOCKET_ERROR)
{
err = WSAGetLastError();
if(err != WSA_IO_PENDING)
{
return err;
}
} err = WSAGetOverlappedResult(m_wsaServerSocket,
&SendOverlapped,
&BytesSend,
TRUE,
&Flags);
if(err != TRUE)
{
return WSAGetLastError();
} return err;
}
int CServerNetwork::CleanupNetwork()
{
// When the application is finished networking, close the socket.
closesocket(m_wsaServerSocket); //---------------------------------------------
// Clean up and quit.
WSACleanup(); return 0;
}
现在有些明白了,确实是用的阻塞sock,那么recv是一定可以执行完的
这个帖子结了,还有写问题,另开个贴吧