Em đang học lập trình giao tiếp theo chuẩn UDP bằng Socket trong VC++. Em lập trình server gửi dữ liệu cho client nhưng gửi với dữ liệu lớn thì không gửi được em tham khảo trên:
http://www.codeproject.com/KB/IP/ser...w=Quick&fr=276
với chương trình trên website em gửi dữ liệu nhỏ hơn 283bytes thì nhận được còn lớn hơn thì chương trình báo lỗi: "Connection Abandonned" .
Mong các bác chỉ bảo: Nguyên nhân này do đâu? Liệu chương trình của em có phải do bộ đệm buffer nhỏ không? để truyền với các packet lớn (khoảng 900bytes) thì phải làm thế nào???
///////////////////////////////////////////////////////////////////////////////
// ReadComm
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// Reads the Socket Communication (doc giao tiep Socket)
// PARAMETERS:
// LPBYTE lpBuffer: buffer to place new data(vung dem de luu du lieu moi)
// DWORD dwSize: maximum size of buffer (kich thuoc lon nhat cua vung dem)
// DWORD dwTimeout: timeout to use in millisecond
///////////////////////////////////////////////////////////////////////////////
DWORD CSocketComm::ReadComm(LPBYTE lpBuffer, DWORD dwSize, DWORD dwTimeout)
{
_ASSERTE( IsOpen() );
_ASSERTE( lpBuffer != NULL );
if (lpBuffer == NULL || dwSize < 1L)
return 0L;
fd_set fdRead = { 0 };
TIMEVAL stTime;
TIMEVAL *pstTime = NULL;
if ( INFINITE != dwTimeout ) {
stTime.tv_sec = dwTimeout/1000;
stTime.tv_usec = (dwTimeout%1000)*1000;
pstTime = &stTime;
}
SOCKET s = (SOCKET) m_hComm;
// Set Descriptor
if ( !FD_ISSET( s, &fdRead ) )
FD_SET( s, &fdRead );
// Select function set read timeout
DWORD dwBytesRead = 0L;
int res = select( s+1, &fdRead, NULL, NULL, pstTime );
if ( res > 0)
{
if (IsBroadcast() || IsSmartAddressing())
{
SockAddrIn sockAddr;
sockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int nLen = sockAddr.Size();
int nOffset = IsSmartAddressing() ? nLen : 0; // use offset for Smart addressing
if ( dwSize < (DWORD) nOffset) // error - buffer to small
{
SetLastError( ERROR_INVALID_USER_BUFFER );
return -1L;
}
LPSTR lpszData = (LPSTR)(lpBuffer + nOffset);
res = recvfrom( s, lpszData, dwSize-nOffset, 0, sockAddr, &nLen);
// clear 'sin_zero', we will ignore them with 'SockAddrIn' anyway!
memset(&sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
// Lock the list...
LockList();
m_AddrList.remove( sockAddr );
if ( res >= 0)
{
// insert unique address
m_AddrList.insert(m_AddrList.end(), sockAddr);
if (IsSmartAddressing())
{
memcpy(lpBuffer, &sockAddr, sockAddr.Size());
res += sockAddr.Size();
}
}
else if (WSAGetLastError() == WSAECONNRESET && m_AddrList.size() == 1)
{
// recvfrom doesn't always return the connection address for last connection
m_AddrList.clear();
}
UnlockList(); // unlock this object addresses-list
}
else
{
res = recv( s, (LPSTR)lpBuffer, dwSize, 0);
}
}
dwBytesRead = (DWORD)((res > 0)?(res) : (-1L));
return dwBytesRead;
}
///////////////////////////////////////////////////////////////////////////////
// Run
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// This function runs the main thread loop
// this implementation can be overloaded.
// This function calls CSocketComm::OnDataReceived() (Virtual Function)
// PARAMETERS:
// NOTES:
// You should not wait on the thread to end in this function or overloads
///////////////////////////////////////////////////////////////////////////////
void CSocketComm::Run()
{
stMessageProxy stMsgProxy;
DWORD dwBytes = 0L;
DWORD dwTimeout = INFINITE;
LPBYTE lpData = (LPBYTE)&stMsgProxy;
DWORD dwSize = sizeof(stMsgProxy);
bool bSmartAddressing = IsSmartAddressing();
if ( !bSmartAddressing )
{
lpData = stMsgProxy.byData;
dwSize = sizeof(stMsgProxy.byData);
}
// Should we run as server mode
if (IsServer() && !bSmartAddressing)
{
if (!IsBroadcast())
{
SOCKET sock = (SOCKET) m_hComm;
sock = WaitForConnection( sock );
// Get new connection socket
if (sock != INVALID_SOCKET)
{
ShutdownConnection( (SOCKET) m_hComm);
m_hComm = (HANDLE) sock;
OnEvent( EVT_CONSUCCESS, NULL ); // connect
}
else
{
// Do not send event if we are closing
if (IsOpen())
OnEvent( EVT_CONFAILURE, NULL ); // wait fail
return;
}
}
}
else
{
GetPeerName( stMsgProxy.address );
}
while( IsOpen() )
{
// Blocking mode: Wait for event
dwBytes = ReadComm(lpData, dwSize, dwTimeout);
// Error? - need to signal error
if (dwBytes == (DWORD)-1L)
{
// Do not send event if we are closing
if (IsOpen())
{
if ( bSmartAddressing )
{
RemoveFromList( stMsgProxy.address );
}
OnEvent( EVT_CONDROP, &stMsgProxy.address); // lost connection
}
// special case for UDP, alert about the event but do not stop
if ( bSmartAddressing )
continue;
else
break;
}
// Chars received?
if ( bSmartAddressing && dwBytes == sizeof(SOCKADDR_IN))
{
OnEvent( EVT_ZEROLENGTH, NULL );
}
else if (dwBytes > 0L)
{
OnDataReceived( lpData, dwBytes);
}
Sleep(0);
}
}
///////////////////////////////////////////////////////////////////////////////
// SocketThreadProc
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// Socket Thread function. This function is the main thread for socket
// communication - Asynchronous mode.
// PARAMETERS:
// LPVOID pParam : Thread parameter - a CSocketComm pointer
// NOTES:
///////////////////////////////////////////////////////////////////////////////
UINT WINAPI CSocketComm::SocketThreadProc(LPVOID pParam)
{
CSocketComm* pThis = reinterpret_cast<CSocketComm*>( pParam );
_ASSERTE( pThis != NULL );
pThis->Run();
return 1L;
} // end SocketThreadProc
http://www.codeproject.com/KB/IP/ser...w=Quick&fr=276
với chương trình trên website em gửi dữ liệu nhỏ hơn 283bytes thì nhận được còn lớn hơn thì chương trình báo lỗi: "Connection Abandonned" .
Mong các bác chỉ bảo: Nguyên nhân này do đâu? Liệu chương trình của em có phải do bộ đệm buffer nhỏ không? để truyền với các packet lớn (khoảng 900bytes) thì phải làm thế nào???
///////////////////////////////////////////////////////////////////////////////
// ReadComm
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// Reads the Socket Communication (doc giao tiep Socket)
// PARAMETERS:
// LPBYTE lpBuffer: buffer to place new data(vung dem de luu du lieu moi)
// DWORD dwSize: maximum size of buffer (kich thuoc lon nhat cua vung dem)
// DWORD dwTimeout: timeout to use in millisecond
///////////////////////////////////////////////////////////////////////////////
DWORD CSocketComm::ReadComm(LPBYTE lpBuffer, DWORD dwSize, DWORD dwTimeout)
{
_ASSERTE( IsOpen() );
_ASSERTE( lpBuffer != NULL );
if (lpBuffer == NULL || dwSize < 1L)
return 0L;
fd_set fdRead = { 0 };
TIMEVAL stTime;
TIMEVAL *pstTime = NULL;
if ( INFINITE != dwTimeout ) {
stTime.tv_sec = dwTimeout/1000;
stTime.tv_usec = (dwTimeout%1000)*1000;
pstTime = &stTime;
}
SOCKET s = (SOCKET) m_hComm;
// Set Descriptor
if ( !FD_ISSET( s, &fdRead ) )
FD_SET( s, &fdRead );
// Select function set read timeout
DWORD dwBytesRead = 0L;
int res = select( s+1, &fdRead, NULL, NULL, pstTime );
if ( res > 0)
{
if (IsBroadcast() || IsSmartAddressing())
{
SockAddrIn sockAddr;
sockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int nLen = sockAddr.Size();
int nOffset = IsSmartAddressing() ? nLen : 0; // use offset for Smart addressing
if ( dwSize < (DWORD) nOffset) // error - buffer to small
{
SetLastError( ERROR_INVALID_USER_BUFFER );
return -1L;
}
LPSTR lpszData = (LPSTR)(lpBuffer + nOffset);
res = recvfrom( s, lpszData, dwSize-nOffset, 0, sockAddr, &nLen);
// clear 'sin_zero', we will ignore them with 'SockAddrIn' anyway!
memset(&sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
// Lock the list...
LockList();
m_AddrList.remove( sockAddr );
if ( res >= 0)
{
// insert unique address
m_AddrList.insert(m_AddrList.end(), sockAddr);
if (IsSmartAddressing())
{
memcpy(lpBuffer, &sockAddr, sockAddr.Size());
res += sockAddr.Size();
}
}
else if (WSAGetLastError() == WSAECONNRESET && m_AddrList.size() == 1)
{
// recvfrom doesn't always return the connection address for last connection
m_AddrList.clear();
}
UnlockList(); // unlock this object addresses-list
}
else
{
res = recv( s, (LPSTR)lpBuffer, dwSize, 0);
}
}
dwBytesRead = (DWORD)((res > 0)?(res) : (-1L));
return dwBytesRead;
}
///////////////////////////////////////////////////////////////////////////////
// Run
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// This function runs the main thread loop
// this implementation can be overloaded.
// This function calls CSocketComm::OnDataReceived() (Virtual Function)
// PARAMETERS:
// NOTES:
// You should not wait on the thread to end in this function or overloads
///////////////////////////////////////////////////////////////////////////////
void CSocketComm::Run()
{
stMessageProxy stMsgProxy;
DWORD dwBytes = 0L;
DWORD dwTimeout = INFINITE;
LPBYTE lpData = (LPBYTE)&stMsgProxy;
DWORD dwSize = sizeof(stMsgProxy);
bool bSmartAddressing = IsSmartAddressing();
if ( !bSmartAddressing )
{
lpData = stMsgProxy.byData;
dwSize = sizeof(stMsgProxy.byData);
}
// Should we run as server mode
if (IsServer() && !bSmartAddressing)
{
if (!IsBroadcast())
{
SOCKET sock = (SOCKET) m_hComm;
sock = WaitForConnection( sock );
// Get new connection socket
if (sock != INVALID_SOCKET)
{
ShutdownConnection( (SOCKET) m_hComm);
m_hComm = (HANDLE) sock;
OnEvent( EVT_CONSUCCESS, NULL ); // connect
}
else
{
// Do not send event if we are closing
if (IsOpen())
OnEvent( EVT_CONFAILURE, NULL ); // wait fail
return;
}
}
}
else
{
GetPeerName( stMsgProxy.address );
}
while( IsOpen() )
{
// Blocking mode: Wait for event
dwBytes = ReadComm(lpData, dwSize, dwTimeout);
// Error? - need to signal error
if (dwBytes == (DWORD)-1L)
{
// Do not send event if we are closing
if (IsOpen())
{
if ( bSmartAddressing )
{
RemoveFromList( stMsgProxy.address );
}
OnEvent( EVT_CONDROP, &stMsgProxy.address); // lost connection
}
// special case for UDP, alert about the event but do not stop
if ( bSmartAddressing )
continue;
else
break;
}
// Chars received?
if ( bSmartAddressing && dwBytes == sizeof(SOCKADDR_IN))
{
OnEvent( EVT_ZEROLENGTH, NULL );
}
else if (dwBytes > 0L)
{
OnDataReceived( lpData, dwBytes);
}
Sleep(0);
}
}
///////////////////////////////////////////////////////////////////////////////
// SocketThreadProc
///////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:
// Socket Thread function. This function is the main thread for socket
// communication - Asynchronous mode.
// PARAMETERS:
// LPVOID pParam : Thread parameter - a CSocketComm pointer
// NOTES:
///////////////////////////////////////////////////////////////////////////////
UINT WINAPI CSocketComm::SocketThreadProc(LPVOID pParam)
{
CSocketComm* pThis = reinterpret_cast<CSocketComm*>( pParam );
_ASSERTE( pThis != NULL );
pThis->Run();
return 1L;
} // end SocketThreadProc
Comment