📄 tcpip.cpp
字号:
// Close the socket
//
nError = closesocket(this->m_Socket);
if (SOCKET_ERROR == nError)
{
TCHAR szMsg[256];
nError = WSAGetLastError();
TRACE("TCP: Attempt to close socket returned error: %d\n", nError);
sprintf(szMsg,
"Attempt to close socket for %s returned error: %d",
m_szIpAddress,
nError);
DisplayMessage(szMsg);
}
else
{
TRACE("TCP: Socket closed\n");
}
m_Socket = INVALID_SOCKET;
this->m_bSocketState = SOCKET_CLOSED;
this->m_dwConnectState = DRV_NOT_CONNECTED;
return(dwErrorCode);
}
//
// @mfunc Connect - In TcpIp Client Mode
// This function connects the client to the specified server
//
// @parm unsigned short int |uPortNumber | port number of server application
//
// @rvalue DRV_CONNECTED | If connection successful
//
// @rvalue DRV_CONNECTING | If connection still in progress
//
// @rvalue DRV_CONNECT_FAILED | If connection failed
//
// @rvalue DRV_NOT_CONNECTED | If cannot connect
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::Connect(unsigned short int uPortNumber)
{
DWORD dwErrorCode = IO_SUCCESS;
// This is a client not server. Just go away.
if (!this->m_bClient)
{
dwErrorCode = IO_CLIENT_ERR;
return(dwErrorCode);
}
if (m_Socket == INVALID_SOCKET)
{
dwErrorCode = Open();
if (IO_SUCCESS != dwErrorCode)
{
//
// Error in Creating Socket
//
m_dwStatus = dwErrorCode;
}
}
//
// If this is a UDP the you do not need connect.
// Just copy the parameters for the address and port
if (!this->m_bTcp)
{
m_uPortNumber = uPortNumber;
if (this->m_lIpAddress != INADDR_ANY)
{
this->m_sSocketAddress.sin_family = AF_INET;
this->m_sSocketAddress.sin_addr.S_un.S_addr = this->m_lIpAddress;
this->m_sSocketAddress.sin_port = htons(this->m_uPortNumber);
}
m_dwConnectState = DRV_CONNECTED;
return(m_dwConnectState);
}
// If this is a TCP then continue connecting
switch (m_dwConnectState)
{
case DRV_CONNECTED:
case DRV_CONNECTING:
case DRV_CONNECT_FAILED:
break;
case DRV_NOT_CONNECTED:
{
DWORD lpExitCode = 0;
BOOL bRet = FALSE;
m_uPortNumber = uPortNumber;
m_dwConnectState = DRV_CONNECTING;
if (m_hReadThread != NULL)
{
bRet = GetExitCodeThread(m_hReadThread, &lpExitCode);
if (bRet)
{
if (lpExitCode == STILL_ACTIVE)
{
return(m_dwConnectState);
}
else
{
CloseHandle(m_hReadThread);
m_hReadThread = (HANDLE) NULL;
}
}
else
{
lpExitCode = GetLastError();
m_dwConnectState = DRV_CONNECT_FAILED;
return(m_dwConnectState);
}
}
m_hReadThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ConnectHandler,
(LPVOID)this,
0,
&m_dwReadThreadId);
}
default:
break;
}
return(m_dwConnectState);
}
//
//
// FUNCTION: (LPTHREAD_START_ROUTINE)ConnectHandler
//
// This function is the start address for the
// connection thread
//
BOOL CTcpIp::ConnectHandler(IN LPVOID ptr)
{
CTcpIp *pObj = (CTcpIp *)ptr;
int nError;
unsigned long uNonBlock = 0;
// This is a client not server. Just go away.
if (!pObj->m_bClient)
{
pObj->m_dwConnectState = DRV_NOT_CONNECTED;
return(FALSE);
}
//
// If this is a UDP the you do not need connect.
if (!pObj->m_bTcp)
{
return(FALSE);
}
if (pObj->m_Socket == INVALID_SOCKET)
{
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
TRACE("TCP: Connect Handler Failed. Socket NULL ...\n");
return(FALSE);
}
pObj->m_dwConnectState = DRV_CONNECTING;
TRACE("TCP: Connecting ...\n");
//
// Set to blocking mode. We do the connect first and
// then set it to non-blocking later on.
//
nError = ioctlsocket(pObj->m_Socket, FIONBIO, &uNonBlock);
if (SOCKET_ERROR == nError)
{
// pObj->m_dwConnectState = DRV_CONNECT_FAILED;
}
if (NULL == pObj->m_sHost)
{
pObj->m_sHost = gethostbyaddr((char *)&pObj->m_lIpAddress,
sizeof(pObj->m_lIpAddress),
AF_INET);
if (NULL == pObj->m_sHost)
{
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("Unable to resolve Ip Address", FALSE);
return(FALSE);
}
}
if (NULL != pObj->m_sHost)
{
TCHAR szConnectMsg[256];
sprintf(szConnectMsg,
"Attempting connection to %s at port %d",
pObj->m_szIpAddress,
pObj->m_uPortNumber);
pObj->DisplayMessage(szConnectMsg);
pObj->m_sSocketAddress.sin_family = AF_INET;
pObj->m_sSocketAddress.sin_addr.S_un.S_addr = pObj->m_lIpAddress;
pObj->m_sSocketAddress.sin_port = htons(pObj->m_uPortNumber);
nError = connect(pObj->m_Socket, (LPSOCKADDR)&pObj->m_sSocketAddress,
sizeof(struct sockaddr_in));
if (SOCKET_ERROR == nError)
{
DWORD dwConnectError = WSAGetLastError();
switch (dwConnectError)
{
case WSAEADDRINUSE:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("The specified address is already in use", FALSE);
break;
case WSAEADDRNOTAVAIL:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("The specified address is not available from the local machine", FALSE);
break;
case WSAEAFNOSUPPORT:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("Addresses in the specified family cannot be used with this socket", FALSE);
break;
case WSAECONNREFUSED:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("The attempt to connect was forcefully rejected", FALSE);
break;
case WSAENETUNREACH:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("The network cannot be reached from this host at this time", FALSE);
break;
case WSAENOBUFS:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("No buffer space is available. The socket cannot be connected", FALSE);
break;
case WSAETIMEDOUT:
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError("Attempt to connect timed out without establishing a connection", FALSE);
break;
case WSAEISCONN:
pObj->m_dwConnectState = DRV_CONNECTED;
pObj->ReportConnectError("Attempt to connect but already connected", FALSE);
break;
case WSAEALREADY:
pObj->m_dwConnectState = DRV_CONNECTING;
pObj->ReportConnectError("Already in progress", FALSE);
break;
case WSAEWOULDBLOCK:
pObj->m_dwConnectState = DRV_CONNECTING;
pObj->ReportConnectError("It would have blocked",FALSE);
break;
default:
{
TCHAR szCntErr[80];
sprintf(szCntErr, "connect() failed for unknown reason: %d", dwConnectError);
pObj->m_dwConnectState = DRV_CONNECT_FAILED;
pObj->ReportConnectError(szCntErr, FALSE);
}
break;
}
}
else
{
//
// Device Connected - Successfully.
// Change State to Connected.
//
pObj->m_dwConnectState = DRV_CONNECTED;
pObj->ReportConnectError(NULL, TRUE);
//
// Set to non-blocking mode
//
uNonBlock = 1;
nError = ioctlsocket(pObj->m_Socket, FIONBIO, &uNonBlock);
if (SOCKET_ERROR == nError)
{
pObj->DisplayMessage("Unable to set socket to non-blocking mode");
}
}
}
return(TRUE);
}
//
// @mfunc DisConnect - In TcpIp Client Mode
// This function does a shutdown for the connected socket,
//
// @parm none
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::DisConnect()
{
DWORD dwErrorCode = IO_SUCCESS;
BOOL bOption = 1;
int nError = 0, nIndex = 0;
char szDiscardBuf[INPUT_BUFFER_SIZE];
// This is a client not server. Just go away.
if (!this->m_bClient)
{
dwErrorCode = IO_CLIENT_ERR;
return(dwErrorCode);
}
if (this->m_Socket == INVALID_SOCKET)
{
return(dwErrorCode);
}
//
// Set to non-blocking mode, (just in case...)
//
unsigned long uNonBlock = 1;
nError = ioctlsocket(this->m_Socket, FIONBIO, &uNonBlock);
if (m_bTcp)
{
// Half-close the connection to close neatly (NOTE: we ignore the
// return from this function because some BSD-based WinSock
// implementations fail shutdown() with WSAEINVAL if a TCP reset
// has been recieved. In any case, if it fails it means the
// connection is already closed anyway, so it doesn't matter.)
nError = shutdown(this->m_Socket, SD_SEND);
// Discard any data received on this socket
// until no more data, EOF or error.
for (nError = 1; (nError && (nError != SOCKET_ERROR));)
{
// If no data recieved on this socket recv() will return zero.
// If socket is invalid, already closed or some other problem occoured
// recv() will return SOCKET_ERROR
// else if there is more data, recv() will return a non-zero value.
nError = recv(this->m_Socket, (LPSTR)szDiscardBuf, INPUT_BUFFER_SIZE, 0);
Sleep(5);
}// End of for loop
}// End of if (m_bTcp) loop
//
// Set the DONTLINGER option so it connection will be aborted and
// return immediately.
//
setsockopt(this->m_Socket, SOL_SOCKET, SO_DONTLINGER, (TCHAR *)&bOption, sizeof(bOption));
this->m_dwConnectState = DRV_NOT_CONNECTED;
return(dwErrorCode);
}
//
// @mfunc Send - (Overloaded) In TcpIp Client Mode
// This function sends request or data to a connected server
//
// @parm IN unsigned char * | pBuffer | Buffer to send
//
// @parm IN DWORD | dwSize | Number of bytes to send
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_SEND_ERROR | If send failed
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::Send(IN unsigned char *pBuffer, IN DWORD dwSize)
{
int nError;
DWORD dwBytesSent = 0, dwBytesLeftToSend, dwBytesTotalSent = 0,
dwErrorCode = IO_SUCCESS;
WSABUF sNetBuffer;
TCHAR szMsg[256];
// This is a client not server. Just go away.
if (!this->m_bClient)
{
dwErrorCode = IO_CLIENT_ERR;
return(dwErrorCode);
}
if (DRV_CONNECTED == this->m_dwConnectState)
{
dwBytesLeftToSend = dwSize;
sNetBuffer.len = dwSize;
sNetBuffer.buf = (char *)pBuffer;
//
// Now actually send data.
// Note: This can be used for both TCP and UDP protocols.
// However, on connectionless sockets (UDP) only if they
// have a stipulated default peer address established through
// the connect or WSAConnect function.
//
if (this->m_bTcp)
{
// If this is a TCP
nError = WSASend(this->m_Socket,
(LPWSABUF)&sNetBuffer,
1,
&dwBytesSent,
0,
(WSAOVERLAPPED *)&this->m_WriteOverlapped,
NULL);
}
else
{
// If this is a UDP
nError = WSASendTo(this->m_Socket,
(LPWSABUF)&sNetBuffer,
1,
&dwBytesSent,
0,
(LPSOCKADDR)&m_sSocketAddress,
m_nSocketAddressSize,
(WSAOVERLAPPED *)&this->m_WriteOverlapped,
NULL);
}
if (ERROR_SUCCESS == nError)
{
dwErrorCode = IO_SUCCESS;
// calculate what's left to send
dwBytesTotalSent += dwBytesSent;
dwBytesLeftToSend = dwSize - dwBytesTotalSent;
}
else if (nError == SOCKET_ERROR)
{
nError = WSAGetLastError();
switch (nError)
{
// A successful WSAStartup must occour
case WSANOTINITIALISED :
sprintf(szMsg, "Send Error %ud Successful startup not occoured for Ip Address %s", nError, this->m_szIpAddress);
DisplayMessage(szMsg);
this->Close();
this->Open();
break;
// The network subsystem has failed
case WSAENETDOWN :
sprintf(szMsg, "Send Error %ud Network Sub-system failed for Ip Address %s", nError, this->m_szIpAddress);
DisplayMessage(szMsg);
this->Close();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -