📄 cesocket.cpp
字号:
//Make sure the socket was created
if(s == INVALID_SOCKET)
{
m_errorCode = WSAENOTSOCK;
return FALSE;
}
//We cannot connect if the socket is already connected or accepting
if(m_socketState > CREATED)
{
m_errorCode = WSAEISCONN;
return FALSE;
}
//Check port values
if(localPort > 65535)
{
m_errorCode = WSAEINVAL;
return FALSE;
}
memset(&m_localAddress, 0, sizeof(SOCKADDR_IN));
m_localAddress.sin_family = AF_INET;
m_localAddress.sin_port = htons(localPort);
m_localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (SOCKADDR*) &m_localAddress, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
m_errorCode = WSAGetLastError();
return FALSE;
}
//UDP needs only bind
if(m_socketType == SOCK_DGRAM)
{
m_socketState = ACCEPTING;
m_udpReadyToSend = FALSE;
//Start reading thread
m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
return TRUE;
}
//The following is TCP listen + accept code
if(listen(s, maxConn) == SOCKET_ERROR)
{
m_errorCode = WSAGetLastError();
return FALSE;
}
m_socketState = ACCEPTING;
m_acceptThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
return TRUE;
}
void CCESocket::AcceptServiceSocket(SOCKET serviceSocket)
{
SOCKADDR_IN peerName;
int nameSize = sizeof(SOCKADDR_IN);
//Is it a valid socket?
if(serviceSocket == INVALID_SOCKET)
return;
//Is it connected?
if(getpeername(serviceSocket, (SOCKADDR*) &peerName, &nameSize) == SOCKET_ERROR)
{
shutdown(serviceSocket, SD_BOTH);
closesocket(serviceSocket);
return;
}
Disconnect();
s = serviceSocket;
if(m_recvBufSize == 0)
m_recvBufSize = TCPBUFFERSIZE;
m_socketState = CONNECTED;
m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
}
DWORD WINAPI CCESocket::StartThread(LPVOID pParam)
{
CCESocket *parent = (CCESocket*) pParam;
if(parent->m_socketState == ACCEPTING && parent->m_socketType == SOCK_STREAM)
parent->AcceptThread();
else
parent->ReadThread();
return 0;
}
void CCESocket::AcceptThread()
{
SOCKET serviceSocket;
m_acceptThreadState = RUNNING;
do
{
memset(&m_remoteAddress, 0, sizeof(SOCKADDR_IN));
serviceSocket = accept(s, (SOCKADDR*) &m_remoteAddress, &m_receiveAddrSz);
if(serviceSocket == SOCKET_ERROR)
{
m_errorCode = WSAGetLastError();
break;
}
//Accepts a new connection
if(!OnAccept(serviceSocket))
{
shutdown(serviceSocket, SD_BOTH);
closesocket(serviceSocket);
}
} while(m_acceptThreadState == RUNNING);
m_acceptThreadState = CLOSING;
if(m_socketState > DISCONNECTING)
{
Disconnect();
OnClose(EVN_SERVERDOWN);
}
// Self terminate the thread
m_acceptThreadState = CLOSED;
m_acceptThread = NULL;
ExitThread(WM_QUIT);
}
// Read any incoming data as well as detect the connected lost/reset
void CCESocket::ReadThread()
{
int bytesRead, bufSize;
DataPacket *data;
char * buf;
m_readThreadState = RUNNING;
do
{
//m_recvBuffSize can change dynamically so we must track its changes
bufSize = m_recvBufSize;
buf = new char[bufSize];
//Blocking receive
switch(m_socketType)
{
case SOCK_STREAM:
bytesRead = recv(s, buf, bufSize, 0);
break;
case SOCK_DGRAM:
bytesRead = recvfrom(s, buf, bufSize, 0, (SOCKADDR*) &m_localAddress, &m_receiveAddrSz);
break;
}
//If there was an error exit thread and notify owner with OnClose
if(bytesRead == SOCKET_ERROR || bytesRead <= 0)
{
m_errorCode = WSAGetLastError();
m_udpReadyToSend = FALSE;
//This happens when we try to sendto data to a client host that closed its receiving
//port. In this case we restart revfrom preventing further sendto until a new
//request from a client host.
if(m_socketType == SOCK_DGRAM && m_errorCode == WSAECONNRESET && m_socketState == ACCEPTING)
{
delete[] buf;
//Notify that a remote connection closed
OnClose(EVN_CONNLOST);
continue;
}
break;
}
m_udpReadyToSend = TRUE;
//If the client doesn't accepts the raw packet store it in the buffer
if(!OnReceive(buf, bytesRead))
{
data = new DataPacket;
data->len = bytesRead;
data->buf = buf;
data->pos = buf;
//AddTail modifies internal list pointers. That's why we
//need to lock while updating
#ifdef _WCE_SECTION
EnterCriticalSection(&CCESocket::m_readLock);
#else
CSingleLock csl(&CCESocket::m_readLock);
csl.Lock();
#endif
m_ReadBuffer.AddTail(data);
#ifdef _WCE_SECTION
LeaveCriticalSection(&CCESocket::m_readLock);
#else
csl.Unlock();
#endif
m_availableData += bytesRead;
//Notify that there are available data
OnReceive();
}
} while(m_readThreadState == RUNNING);
delete[] buf;
m_readThreadState = CLOSING;
if(m_socketState > DISCONNECTING)
{
if(m_socketType == SOCK_STREAM)
{
Disconnect();
OnClose(EVN_CONNCLOSED);
}
else
{
m_socketState = CREATED;
if(m_socketState == ACCEPTING)
OnClose(EVN_SERVERDOWN);
else
OnClose(EVN_CONNLOST);
}
}
// Self terminate the thread
m_readThreadState = CLOSED;
m_readThread = NULL;
// ExitThread(WM_QUIT);
}
int CCESocket::Read(char* buf, int len)
{
int readBytes;
DataPacket *data;
if(!buf || len <= 0)
return 0;
readBytes = 0;
while (m_ReadBuffer.GetNumEntries() > 0 && len > 0)
{
data = m_ReadBuffer.GetHead();
//copies head packet and removes it from the buffer
if(len >= data->len)
{
memcpy(&buf[readBytes], data->pos, data->len);
len -= data->len;
readBytes += data->len;
delete[] data->buf;
//RemoveHead modifies internal list pointers. That's why we
//need to lock while updating
#ifdef _WCE_SECTION
EnterCriticalSection(&CCESocket::m_readLock);
#else
CSingleLock csl(&CCESocket::m_readLock);
csl.Lock();
#endif
delete m_ReadBuffer.RemoveHead();
#ifdef _WCE_SECTION
LeaveCriticalSection(&CCESocket::m_readLock);
#else
csl.Unlock();
#endif
}
//copies len data from the head packet and (fast) resizes it
else
{
memcpy(&buf[readBytes], data->pos, len);
data->len -= len;
data->pos += len;
readBytes += len;
break;
}
}
m_availableData -= readBytes;
return readBytes;
}
bool CCESocket::ReadString(CString &str)
{
bool strFound;
int strSize, strPos;
DataPacket *data;
char *buf;
char eol;
strSize = 0;
strFound = FALSE;
if(m_eolFormat == EOL_NULL)
eol = '\0';
else
eol = '\n';
//We must do a double pass:
// 1) Search for the string termination '\n'
// 2) Copy string data
if(!m_ReadBuffer.IsEmpty())
{
//First pass
data = m_ReadBuffer.GetHead();
for(strPos=0; strPos < data->len; strPos++)
if(data->pos[strPos] == eol)
{
strSize = strPos +1;
strFound = TRUE;
break;
}
while(!strFound && !m_ReadBuffer.IsLast())
{
strSize += data->len;
data = m_ReadBuffer.GetNext();
for(strPos=0; strPos < data->len; strPos++)
if(data->pos[strPos] == eol)
{
strSize += strPos +1;
strFound = TRUE;
break;
}
}
//Second pass
if(strFound)
{
strPos = 0;
m_availableData -= strSize;
buf = new char[strSize +1];
buf[strSize] = '\0';
while (strSize > 0)
{
data = m_ReadBuffer.GetHead();
//copies head packet and removes it from the buffer
if(strSize >= data->len)
{
memcpy(&buf[strPos], data->pos, data->len);
strSize -= data->len;
strPos += data->len;
delete[] data->buf;
//RemoveHead modifies internal list pointers. That's why we
//need to lock while updating
#ifdef _WCE_SECTION
EnterCriticalSection(&CCESocket::m_readLock);
#else
CSingleLock csl(&CCESocket::m_readLock);
csl.Lock();
#endif
delete m_ReadBuffer.RemoveHead();
#ifdef _WCE_SECTION
LeaveCriticalSection(&CCESocket::m_readLock);
#else
csl.Unlock();
#endif
}
//copies len data from the head packet and (fast) resizes it
else
{
memcpy(&buf[strPos], data->pos, strSize);
data->len -= strSize;
data->pos += strSize;
break;
}
}
str = buf; //Assign and convert to unicode
delete[] buf;
return TRUE;
}
}
str = _T("");
return FALSE;
}
int CCESocket::GetNumPackets()
{
return m_ReadBuffer.GetNumEntries();
}
int CCESocket::GetPacketSize()
{
if(m_availableData > 0)
return m_ReadBuffer.GetHead()->len;
return 0;
}
bool CCESocket::GetPacket(char*& buf, int* len)
{
DataPacket *data = NULL;
//There's no need to lock while accessing data
if(m_availableData > 0)
{
data = m_ReadBuffer.GetHead();
*len = data->len;
buf = data->buf;
m_availableData -= *len;
//RemoveHead modifies internal list pointers. That's why we
//need to lock while updating
#ifdef _WCE_SECTION
EnterCriticalSection(&CCESocket::m_readLock);
#else
CSingleLock csl(&CCESocket::m_readLock);
csl.Lock();
#endif
delete m_ReadBuffer.RemoveHead();
#ifdef _WCE_SECTION
LeaveCriticalSection(&CCESocket::m_readLock);
#else
csl.Unlock();
#endif
}
return (data != NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -