套接字的非阻塞模式是指套接字在执行操作时,调用的函数不管操作是否完成都会立即返回的工作模式。非阻塞套接字在处理同时建立的多个连接,发送和接收的数据量不均,时间不定等方面具有明显的优势。但这种套接字在使用上存在一定难度。本章讲述套接字的非阻塞模式及其一个远程算数运算套接字程序。
套接字的非阻塞模式
所有windows平台都支持套接字以阻塞模式和非阻塞模式的方式工作。
非阻塞模式
把套接字设置为非阻塞模式,即通知系统内核:在调用WindowsSocketsAPI时,不要让线程随眠,而应该让函数理解返回。在返回时,该函数返回一个错误代码。一个非阻塞模式套接字多次调用recv()的过程如上。前3次调用recv()函数时,内核函数还没有准备好。因此,该函数理解返回WSAEWOULDBLOCK错误代码。第4次调用recv()函数时,数据已经准备好,被负责到应用程序的缓冲区中,recv()返回成功指示,应用程序开始处理数据。
设置套接字的非阻塞模式
当使用socket(),WSASocket()创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket(),将该套接字设置为非阻塞模式。
套接字设置为非阻塞模式后,在调用WindowsSocketsAPI函数时,调用函数会立即返回。大多数情况下,这些函数调用都会调用“失败”,并返回WSAEWOULDBLOCK错误代码。说明请求的操作在调用期间内没有时间完成。通常,应用程序需要重复调用该函数,直到获得成功返回代码。
WSAEWOULDBLOCK的含义 |
函数名 |
说明 |
accept(),WSAAcept() |
应用程序没有接收到连接请求 |
recv(),WSARecv(),recvfrom(),WSARecvfrom() |
接收缓冲区没有收到数据 |
send(),WSASend(),sendto(),WSASendto() |
发送缓冲区此时不可用 |
connect(),WSAConnect() |
连接未能立即完成 |
closesocket() |
通常情况下意味着应用程序使用SO_LINGER选项并且设置一个非零的超时值,调用了setsocketopt() |
需要说明的是并非所有的WindowsSocketsAPI在非阻塞模式下调用,都会返回WSEWOULDBLOCK错误。eg:bind(),listen()。
要将套接字设置为非阻塞模式,除了使用ioctlsocket()函数之外,还可以使用WSAAsyncSelect()(第7章讲解),WSAEventselect()(第8章讲解)。当调用该函数时,套接字会自动地设置为非阻塞方式。
非阻塞模式套接字的优势和不足
由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码,并做好应对“失败”的准备。应用程序连续不断的调用这个函数,直到它返回成功指示为止。本章程序清单中,在While循环体内不断的调用recv(),以读入1024个字节的数据。这种做法很浪费系统资源。
有人使用MSG_PEEK标志调用recv()查看缓冲区中是否有数据可读。同样,这种方法也不好,因为该做法对系统造成的开销是很大的,并且应用程序至少要调用recv()两次,才能实际地读入数据。较好的做法是,使用套接字的“I/O模型”(第6,7,8,9,10章来讲解)来判断非阻塞套接字是否可读可写。
非阻塞模式套接字与阻塞套接字相比,使用较复杂。使用非阻塞模式套接字,需要编写更多的代码,以便在每个WindowsSocketAPI函数调用中,对收到的WSAEWOULDBLOCK错误进行处理。因此,非阻塞套接字便显得有些难于使用。
但是,非阻塞套接字在控制建立的多个连接,在数据的收发量不均,时间不定等方面,明显具有优势。通常情况下,可考虑使用套接字的“I/O模型”,它有助于应用程序通过异步方法,同时对一个或多个套接字的通信加以管理。
远程算数运算程序
本程序实现一个可以同时为多个客户端提供服务的远程算数运算程序。客户端和服务器端都使用非阻塞套接字。
NoBlockServer
client.h
- #pragma once
- #include <WinSock2.h>
- #define TIMEFOR_THREAD_CLIENT 500//线程睡眠时间
- #define MAX_NUM_CLIENT 10//接受的客户端连接最多数量
- #define MAX_NUM_BUF 48//缓冲区的最大长度
- #define INVALID_OPERATOR 1 //无效的操作符
- #define INVALID_NUM 2 //分母为0
- typedef struct _head
- {
- char type;
- unsigned short len;
- }hdr,*phdr;
- #define HEADERLEN (sizeof(hdr))//头长度
- typedef struct _data
- {
- char buf[MAX_NUM_BUF];
- }DATABUF,*pDataBuf;
-
-
- class Client
- {
- public:
- Client(const SOCKET sClient,const sockaddr_in &addrClient);
- virtual ~Client(void);
- public:
- BOOL StartRunning();
- void HandleData(const char* pExpr);
- BOOL IsConning()
- {
- return m_bConning;
- }
- void DisConning()
- {
- m_bConning=FALSE;
- }
- BOOL IsExit()
- {
- return m_bExit;
- }
- public:
- static DWORD _stdcall RecvDataThread(void* pParam);
- static DWORD _stdcall SendDataThread(void* pParam);
- public:
- SOCKET m_socket;
- sockaddr_in m_addr;
- private:
- DATABUF m_data;
- HANDLE m_hEvent;
- HANDLE m_hThreadSend;
- HANDLE m_hThreadRecv;
- CRITICAL_SECTION m_cs;
- BOOL m_bConning;
- BOOL m_bExit;
- };
client.cpp
- #include "StdAfx.h"
- #include <process.h>
- #include "Client.h"
-
- Client::Client(const SOCKET sClient,const sockaddr_in &addrClient)
- {
- m_hThreadRecv=NULL;
- m_hThreadSend=NULL;
- m_socket=sClient;
- m_addr=addrClient;
- m_bConning=FALSE;
- m_bExit=FALSE;
- memset(m_data.buf,0,MAX_NUM_BUF);
- m_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
- InitializeCriticalSection(&m_cs);
- }
-
- Client::~Client(void)
- {
- closesocket(m_socket);
- m_socket=INVALID_SOCKET;
- DeleteCriticalSection(&m_cs);
- CloseHandle(m_hEvent);
- }
- BOOL Client::StartRunning()
- {
- m_bConning=TRUE;
- if ((m_hThreadRecv=CreateThread(NULL,0,RecvDataThread,this,0,NULL)) == NULL)
- {
- return FALSE;
- }
- else
- {
- CloseHandle(m_hThreadRecv);
- }
- if ((m_hThreadSend = CreateThread(NULL,0,SendDataThread,this,0,NULL)) == NULL)
- {
- return FALSE;
- }
- else
- {
- CloseHandle(m_hThreadSend);
- }
- return TRUE;
- }
- DWORD Client::RecvDataThread(void* pParam)
- {
- Client* pClient=(Client*)pParam;
- int reVal;
- char temp[MAX_NUM_BUF];
- memset(temp,0,MAX_NUM_BUF);
- for (;pClient->m_bConning;)
- {
- reVal = recv(pClient->m_socket,temp,MAX_NUM_BUF,0);
-
- if (reVal == SOCKET_ERROR)
- {
- int nErrCode=WSAGetLastError();
- if (WSAEWOULDBLOCK == nErrCode)
- {
- continue;
- }
- else if( WSAENETDOWN == nErrCode || WSAETIMEDOUT == nErrCode ||WSAECONNRESET == nErrCode)
- {
- break;
- }
- }
-
- if( reVal == 0)
- {
- break;
- }
-
- if (reVal > HEADERLEN)
- {
- printf("server recv:%s\n",temp);
- pClient->HandleData(temp);
- SetEvent(pClient->m_hEvent);
- memset(temp,0,MAX_NUM_BUF);
- }
- Sleep(TIMEFOR_THREAD_CLIENT);
- }
- pClient->m_bConning=FALSE;
- SetEvent(pClient->m_hEvent);
- return 0;
- }
- DWORD Client::SendDataThread(void* pParam)
- {
- Client* pClient=(Client*)pParam;
- for (;pClient->m_bConning;)
- {
-
- if (WAIT_OBJECT_0 == WaitForSingleObject(pClient->m_hEvent,INFINITE))
- {
-
- if (!pClient->m_bConning)
- {
- pClient->m_bExit=TRUE;
- break;
- }
-
- EnterCriticalSection(&pClient->m_cs);
-
- phdr pHeander=(phdr)pClient->m_data.buf;
- printf("server send client:[%d]%s\n",pHeander->len,pClient->m_data.buf);
- int val = send(pClient->m_socket,pClient->m_data.buf,pHeander->len,0);
-
- if (SOCKET_ERROR == val)
- {
- int nErrCode=WSAGetLastError();
- if (nErrCode == WSAEWOULDBLOCK)
- {
- continue;
- }
- else if(WSAENETDOWN == nErrCode || WSAETIMEDOUT == nErrCode || WSAECONNRESET == nErrCode)
- {
-
- LeaveCriticalSection(&pClient->m_cs);
- pClient->m_bConning=FALSE;
- pClient->m_bExit=TRUE;
- break;
- }
- else
- {
-
- LeaveCriticalSection(&pClient->m_cs);
- pClient->m_bConning=FALSE;
- pClient->m_bExit=TRUE;
- break;
- }
- }
-
-
- LeaveCriticalSection(&pClient->m_cs);
-
- ResetEvent(&pClient->m_hEvent);
- }
- }
- return 0;
- }
- void Client::HandleData(const char* pExpr)
- {
- memset(m_data.buf,0,MAX_NUM_BUF);
-
- if ('B' == ((phdr)pExpr)->type)
- {
- EnterCriticalSection(&m_cs);
- phdr pHeaderSend=(phdr)m_data.buf;
- pHeaderSend->type ='B';
- pHeaderSend->len=HEADERLEN+strlen("OK");
- memcpy(m_data.buf+HEADERLEN,"OK",strlen("OK"));
- LeaveCriticalSection(&m_cs);
- }
- else
- {
- int nFirNum,nSecNum,nResult;
- char cOper;
-
- sscanf(pExpr+HEADERLEN,"%d%c%d",&nFirNum,&cOper,&nSecNum);
-
- switch (cOper)
- {
- case '+':
- {
- nResult=nFirNum+nSecNum;
- break;
- }
- case '-':
- {
- nResult=nFirNum-nSecNum;
- break;
- }
- case '*':
- {
- nResult=nFirNum*nSecNum;
- break;
- }
- case '/':
- {
- if(nSecNum == 0)
- nResult=INVALID_NUM;
- else
- nResult=nFirNum/nSecNum;
- break;
- }
- default:
- nResult=INVALID_OPERATOR;
- }
-
- char temp[MAX_NUM_BUF];
- char cEqu='=';
- sprintf(temp,"%d%c%d%c%d",nFirNum,cOper,nSecNum,cEqu,nResult);
-
- EnterCriticalSection(&m_cs);
- phdr pHeaderSend=(phdr)m_data.buf;
- pHeaderSend->type='E';
- pHeaderSend->len=HEADERLEN+strlen(temp);
- memcpy(m_data.buf+HEADERLEN,temp,strlen(temp));
- LeaveCriticalSection(&m_cs);
- }
- }
NoBlockServer.cpp
-
-
-
-
-
-
-
-
-
-
-
- #include "stdafx.h"
- #include <WinSock2.h>
- #include <iostream>
- #include <list>
- #include "Client.h"
- using namespace std;
- #pragma comment(lib,"ws2_32.lib")
- #define TIMEFOR_THREAD_EXIT 5000 //主线程睡眠时间
- #define TIMEFOR_THREAD_HELP 1500 //清理资源线程退出时间
- #define TIMEFOR_THREAD_SLEEP 500 //等待客户端请求线程睡眠时间
- typedef list<Client*> CLIENTLIST;
- CLIENTLIST clientList;
- HANDLE hThreadAccept;
- HANDLE hThreadHelp;
- SOCKET sServer;
- BOOL bServerRunning;
- HANDLE hServerEvent;
- CRITICAL_SECTION csClientList;
-
-
- BOOL InitServer();
- BOOL StartService();
- void StopService();
- BOOL CreateHelperAndAcceptThread();
- void ExitServer();
-
- void InitMember();
- BOOL InitSocket();
-
- DWORD _stdcall HelperThread(void *pParam);
- DWORD _stdcall AcceptThread(void *pParam);
-
- void main()
- {
- if (!InitServer())
- {
- ExitServer();
- return;
- }
- if (!StartService())
- {
- ExitServer();
- return;
- }
- StopService();
- ExitServer();
- system("pause");
- return;
- }
-
- BOOL InitServer()
- {
- InitMember();
- if (!InitSocket())
- {
- return FALSE;
- }
- return TRUE;
- }
- void InitMember()
- {
- InitializeCriticalSection(&csClientList);
-
- hServerEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
- hThreadAccept=NULL;
- hThreadHelp=NULL;
- sServer=INVALID_SOCKET;
- bServerRunning=FALSE;
- clientList.clear();
- }
- BOOL InitSocket()
- {
- WSAData wsData;
- if (WSAStartup(MAKEWORD(2,2),&wsData) != 0)
- {
- return FALSE;
- }
- if ((sServer = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
- {
- return FALSE;
- }
-
- unsigned long ul=1;
- if (ioctlsocket(sServer,FIONBIO,&ul) == SOCKET_ERROR)
- {
- return FALSE;
- }
-
- SOCKADDR_IN addrServ;
- addrServ.sin_family=AF_INET;
- addrServ.sin_addr.s_addr=INADDR_ANY;
- addrServ.sin_port=htons(5000);
- if (bind(sServer,(SOCKADDR*)&addrServ,sizeof(addrServ)) == SOCKET_ERROR)
- {
- return FALSE;
- }
- if (listen(sServer,SOMAXCONN) == SOCKET_ERROR)
- {
- return FALSE;
- }
- printf("start listen...\n");
- return TRUE;
- }
- BOOL StartService()
- {
- return CreateHelperAndAcceptThread();
- }
-
-
-
-
- void StopService()
- {
- printf("tip--->e(E):Exit server. please input:\n");
- char cInput;
- for (;bServerRunning;)
- {
- cin >> cInput;
- if (cInput == 'E' || cInput == 'e')
- {
- if (IDOK == MessageBox(NULL,L"Are you sure?",L"Server",MB_OKCANCEL))
- {
- break;
- }
- else
- {
- Sleep(TIMEFOR_THREAD_EXIT);
- }
- }
- else
- {
- Sleep(TIMEFOR_THREAD_EXIT);
- }
- }
- bServerRunning=FALSE;
- cout<<"Server exit ..."<<endl;
- Sleep(TIMEFOR_THREAD_EXIT);
- WaitForSingleObject(hServerEvent,INFINITE);
- }
- BOOL CreateHelperAndAcceptThread()
- {
- bServerRunning=TRUE;
-
- if ((hThreadHelp=CreateThread(NULL,0,HelperThread,NULL,0,NULL)) == NULL)
- {
- bServerRunning =FALSE;
- cout<<"Server failed!"<<endl;
- return FALSE;
- }
- else
- {
- CloseHandle(hThreadHelp);
- }
-
- if ((hThreadAccept=CreateThread(NULL,0,AcceptThread,NULL,0,NULL)) == NULL)
- {
- bServerRunning =FALSE;
- cout<<"Server failed!"<<endl;
- return FALSE;
- }
- else
- {
- CloseHandle(hThreadAccept);
- }
- cout<<"Server succeded!"<<endl;
- return TRUE;
- }
- void ExitServer()
- {
- DeleteCriticalSection(&csClientList);
- CloseHandle(hServerEvent);
- closesocket(sServer);
- WSACleanup();
- }
-
- DWORD _stdcall HelperThread(void *pParam)
- {
-
-
-
- for (;bServerRunning;)
- {
- EnterCriticalSection(&csClientList);
-
-
- CLIENTLIST::iterator iter=clientList.begin();
- for (;iter != clientList.end();)
- {
- Client* pClient=(Client*)*iter;
- if (pClient->IsExit())
- {
- printf("first server delete a client[%s],id=%d\n",inet_ntoa(pClient->m_addr.sin_addr),pClient->m_socket);
- clientList.erase(iter++);
- delete pClient;
- pClient=NULL;
- }
- else
- {
- iter++;
- }
- }
- LeaveCriticalSection(&csClientList);
- Sleep(TIMEFOR_THREAD_HELP);
- }
-
-
- if (!bServerRunning)
- {
-
- EnterCriticalSection(&csClientList);
- CLIENTLIST::iterator iter=clientList.begin();
- for (;iter != clientList.end();)
- {
- Client* pClient=(Client*)*iter;
-
- if (pClient->IsConning())
- {
- pClient->DisConning();
- }
- ++iter;
- }
- LeaveCriticalSection(&csClientList);
- Sleep(TIMEFOR_THREAD_SLEEP);
-
- EnterCriticalSection(&csClientList);
-
- while(clientList.size() != 0)
- {
- iter = clientList.begin();
- for (;iter != clientList.end();iter++)
- {
- Client* pClient=(Client*)*iter;
- if (pClient->IsExit())
- {
- printf("second server delete a client[%s],id=%d\n",inet_ntoa(pClient->m_addr.sin_addr),pClient->m_socket);
- clientList.erase(iter++);
- delete pClient;
- pClient=NULL;
- }
- }
- Sleep(TIMEFOR_THREAD_SLEEP);
- }
- LeaveCriticalSection(&csClientList);
- }
- clientList.clear();
- SetEvent(hServerEvent);
- return 0;
- }
-
- DWORD _stdcall AcceptThread(void *pParam)
- {
- SOCKET sAccept;
- sockaddr_in addrClient;
- while(bServerRunning)
- {
- memset(&addrClient,0,sizeof(sockaddr_in));
- int lenClient=sizeof(sockaddr_in);
- sAccept=accept(sServer,(sockaddr*)&addrClient,&lenClient);
- if (INVALID_SOCKET == sAccept)
- {
- int nErrCode=WSAGetLastError();
- if (nErrCode == WSAEWOULDBLOCK)
- {
- Sleep(TIMEFOR_THREAD_SLEEP);
- continue;
- }
- else
- {
- return 0;
- }
- }
- else
- {
- Client* pClient=new Client(sAccept,addrClient);
- printf("server accept a client[%s]:%d;id=%d\n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port),sAccept);
- EnterCriticalSection(&csClientList);
- clientList.push_back(pClient);
- LeaveCriticalSection(&csClientList);
- pClient->StartRunning();
- }
- }
- return 0;
- }
NoBlockClient
NoBlockClient.cpp
-
-
-
-
-
-
-
-
-
-
- #include <winsock2.h>
- #include <stdio.h>
- #include <iostream>
- using namespace std;
- #pragma comment(lib,"ws2_32.lib")
-
- #define TIMEFOR_THREAD_EXIT 1000
- #define TIMEFOR_THREAD_SLEEP 500
- #define BUF_MAX_NUM 64
- #define HEADERLEN (sizeof(hdr))
- typedef struct _head
- {
- char type;
- unsigned short len;
- }hdr,*phdr;
- typedef struct _data
- {
- char buf[BUF_MAX_NUM];
- }DATABUF,*pDataBuf;
-
-
- SOCKET sClient;
- HANDLE hThreadSend;
- HANDLE hThreadRecv;
- DATABUF bufSend;
- DATABUF bufRecv;
- CRITICAL_SECTION csSend;
- CRITICAL_SECTION csRecv;
-
- BOOL bSendData;
- HANDLE hEventShowDataResult;
- BOOL bConnected;
- HANDLE arrThread[2];
-
- BOOL InitClient();
- BOOL ConnectServer();
- BOOL CreateSendAndRecvThread();
- void InputAndOutput();
- void ExitClient();
-
- void InitMember();
- BOOL InitSocket();
-
- DWORD _stdcall RecvDataThread(LPVOID pParam);
- DWORD _stdcall SendDataThread(LPVOID pParam);
-
- BOOL PackByebye(const char* pExpr);
- BOOL PackExpression(const char* pExpr);
-
- void ShowConnectMsg(BOOL bConnected);
- void ShowDataResultMsg();
- void ShowTipMsg(BOOL bFirstInput);
-
- int main()
- {
- if (!InitClient())
- {
- ExitClient();
- return 0;
- }
- if (ConnectServer())
- {
- ShowConnectMsg(TRUE);
- }
- else
- {
- ShowConnectMsg(FALSE);
- ExitClient();
- return 0;
- }
- if (!CreateSendAndRecvThread())
- {
- ExitClient();
- return 0;
- }
- InputAndOutput();
- ExitClient();
- system("pause");
- return 0;
- }
- BOOL InitClient()
- {
- InitMember();
- if (!InitSocket())
- {
- return FALSE;
- }
- return TRUE;
- }
- void InitMember()
- {
- InitializeCriticalSection(&csSend);
- InitializeCriticalSection(&csRecv);
-
- sClient=INVALID_SOCKET;
- hThreadRecv=NULL;
- hThreadSend=NULL;
- bConnected=FALSE;
- bSendData=FALSE;
-
- memset(bufRecv.buf,0,BUF_MAX_NUM);
- memset(bufSend.buf,0,BUF_MAX_NUM);
-
-
- hEventShowDataResult=(HANDLE)CreateEvent(NULL,TRUE,FALSE,NULL);
- }
- BOOL InitSocket()
- {
- WSADATA wsd;
- if (WSAStartup(MAKEWORD(2,2),&wsd) != 0)
- {
- return FALSE;
- }
-
- if ((sClient=socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
- {
- return FALSE;
- }
-
-
- unsigned long ul=1;
- if (ioctlsocket(sClient,FIONBIO,&ul) == SOCKET_ERROR)
- {
- return FALSE;
- }
- return TRUE;
- }
- BOOL ConnectServer()
- {
- SOCKADDR_IN addrServ;
- addrServ.sin_family=AF_INET;
- addrServ.sin_addr.s_addr=inet_addr("127.0.0.1");
- addrServ.sin_port=htons(5000);
- int reVal;
- while (1)
- {
- reVal=connect(sClient,(SOCKADDR*)&addrServ,sizeof(addrServ));
-
- if (reVal == SOCKET_ERROR)
- {
- int nErrCode=WSAGetLastError();
- if (nErrCode == WSAEWOULDBLOCK || nErrCode == WSAEINVAL)
- {
- continue;
- }
- else if (nErrCode == WSAEISCONN)
- {
- break;
- }
- else
- {
- return FALSE;
- }
- }
- if(reVal == 0)
- {
- break;
- }
- }
- bConnected=TRUE;
- return TRUE;
- }
- BOOL CreateSendAndRecvThread()
- {
- unsigned long ulThreadId;
- if ((hThreadRecv=CreateThread(NULL,0,RecvDataThread,NULL,0,&ulThreadId)) == NULL)
- {
- return FALSE;
- }
- if ((hThreadSend=CreateThread(NULL,0,SendDataThread,NULL,0,&ulThreadId)) == NULL)
- {
- return FALSE;
- }
- arrThread[0]=hThreadRecv;
- arrThread[1]=hThreadSend;
- return TRUE;
- }
-
-
-
- void InputAndOutput()
- {
- char cInput[BUF_MAX_NUM];
- BOOL bFirstInput=TRUE;
- while(bConnected)
- {
- memset(cInput,0,BUF_MAX_NUM);
- ShowTipMsg(bFirstInput);
- cin >> cInput;
- char* pTemp=cInput;
- if (bFirstInput)
- {
- if (!PackExpression(pTemp))
- {
- continue;
- }
- bFirstInput = FALSE;
- }
- else if (!PackByebye(pTemp))
- {
- if (!PackExpression(pTemp))
- {
- continue;
- }
- }
-
- if (WAIT_OBJECT_0 == WaitForSingleObject(hEventShowDataResult,INFINITE))
- {
- ResetEvent(hEventShowDataResult);
- if (!bConnected)
- {
- break;
- }
- ShowDataResultMsg();
- if (0 == strcmp(bufRecv.buf,"OK"))
- {
- bConnected=FALSE;
- Sleep(TIMEFOR_THREAD_EXIT);
- }
- }
- }
- if (!bConnected)
- {
- ShowConnectMsg(FALSE);
- }
-
- if (WAIT_ABANDONED_0 == WaitForMultipleObjects(2,arrThread,TRUE,INFINITE))
- {
- int nErrCode=GetLastError();
- }
- }
- void ExitClient()
- {
- DeleteCriticalSection(&csSend);
- DeleteCriticalSection(&csRecv);
- CloseHandle(hThreadRecv);
- CloseHandle(hThreadSend);
- closesocket(sClient);
- WSACleanup();
- }
-
- DWORD _stdcall RecvDataThread(LPVOID pParam)
- {
- int reVal;
- char temp[BUF_MAX_NUM];
- memset(temp,0,BUF_MAX_NUM);
- while(bConnected)
- {
- reVal = recv( sClient,temp,BUF_MAX_NUM,0);
- if ( SOCKET_ERROR == reVal)
- {
- int nErrCode = WSAGetLastError();
- if (WSAEWOULDBLOCK == nErrCode)
- {
- Sleep(TIMEFOR_THREAD_SLEEP);
- continue;
- }
- else
- {
- bConnected = FALSE;
- SetEvent(hEventShowDataResult);
- return 0;
- }
- }
- if ( 0 == reVal)
- {
- bConnected = FALSE;
- SetEvent(hEventShowDataResult);
- return 0;
- }
- if ( reVal > HEADERLEN && reVal != -1)
- {
-
- phdr header =(phdr)temp;
- EnterCriticalSection(&csRecv);
- memset(bufRecv.buf,0,BUF_MAX_NUM);
- memcpy(bufRecv.buf,temp + HEADERLEN,header->len - HEADERLEN);
- LeaveCriticalSection(&csRecv);
- SetEvent(hEventShowDataResult);
- memset(temp,0,BUF_MAX_NUM);
- }
- Sleep(TIMEFOR_THREAD_SLEEP);
- }
- return 0;
- }
- DWORD _stdcall SendDataThread(LPVOID pParam)
- {
- while(bConnected)
- {
- if (bSendData)
- {
- EnterCriticalSection(&csSend);
- while(TRUE)
- {
- int nBuflen=((phdr)bufSend.buf)->len;
- int val = send(sClient,bufSend.buf,nBuflen,0);
-
- if (SOCKET_ERROR == val)
- {
- int nErrCode = WSAGetLastError();
- if (WSAEWOULDBLOCK == nErrCode)
- {
- continue;
- }
- else
- {
- LeaveCriticalSection(&csSend);
- bConnected = FALSE;
- SetEvent(hEventShowDataResult);
- return 0;
- }
- }
- bSendData = FALSE;
- break;
- }
- LeaveCriticalSection(&csSend);
- }
- Sleep(TIMEFOR_THREAD_SLEEP);
- }
- return 0;
- }
- BOOL PackByebye(const char* pExpr)
- {
- BOOL reVal = FALSE;
- if (!strcmp("Byebye",pExpr) || !strcmp("byebye",pExpr))
- {
- EnterCriticalSection(&csSend);
- phdr pHeader =(phdr)bufSend.buf;
- pHeader->type='B';
- pHeader->len = HEADERLEN + strlen("Byebye");
- memcpy(bufSend.buf + HEADERLEN,pExpr,strlen(pExpr));
- LeaveCriticalSection(&csSend);
- pHeader = NULL;
- bSendData = TRUE;
- reVal = TRUE;
- }
- return reVal;
- }
- BOOL PackExpression(const char* pExpr)
- {
- char* pTemp = (char*)pExpr;
- while (!*pTemp)
- {
- pTemp++;
- }
- char* pos1=pTemp;
- char* pos2=NULL;
- char* pos3=NULL;
- int len1=0,len2=0,len3=0;
- if ((*pTemp != '+') && (*pTemp != '-') && ((*pTemp < '0') || (*pTemp > '9')))
- {
- return FALSE;
- }
-
- if ((*pTemp++ == '-')&&(*pTemp < '0' || *pTemp > '9'))
- return FALSE;
- --pTemp;
-
- char* pNum = pTemp;
- if (*pTemp == '+'||*pTemp == '-')
- pTemp++;
-
- while (*pTemp >= '0' && *pTemp <= '9')
- pTemp++;
-
- len1 = pTemp - pNum;
-
-
- while(!*pTemp)
- pTemp++;
-
-
- if (('+' != *pTemp) && ('-' != *pTemp) && ('*' != *pTemp) && ('/' != *pTemp))
- return FALSE;
-
- pos2 = pTemp;
- len2 = 1;
-
-
- pTemp++;
-
- while(!*pTemp)
- pTemp++;
-
-
- pos3 = pTemp;
- if (*pTemp < '0' || *pTemp > '9')
- return FALSE;
-
- while (*pTemp >= '0' && *pTemp <= '9')
- pTemp++;
-
- if ('=' != *pTemp)
- return FALSE;
-
- len3 = pTemp - pos3;
-
-
- int nExprlen = len1 + len2 + len3;
-
-
- EnterCriticalSection(&csSend);
-
- phdr pHeader = (phdr)(bufSend.buf);
- pHeader->type = 'E';
- pHeader->len = nExprlen + HEADERLEN;
-
- memcpy(bufSend.buf + HEADERLEN, pos1, len1);
- memcpy(bufSend.buf + HEADERLEN + len1, pos2, len2);
- memcpy(bufSend.buf + HEADERLEN + len1 + len2 , pos3,len3);
- LeaveCriticalSection(&csSend);
- pHeader = NULL;
-
- bSendData = TRUE;
- return TRUE;
- }
- void ShowConnectMsg(BOOL bSuc)
- {
- if (bSuc)
- {
- cout << "* Succeed to connect server! *" << endl;
- }
- else
- {
- cout << "* Fail to connect server! *" << endl;
- }
- }
- void ShowDataResultMsg()
- {
- EnterCriticalSection(&csRecv);
- cout << "***Result: "<<bufRecv.buf <<endl;
- LeaveCriticalSection(&csRecv);
- }
- void ShowTipMsg(BOOL bFirstInput)
- {
- if (bFirstInput)
- {
- cout << "**********************************" << endl;
- cout << "* *" << endl;
- cout << "* Please input expression. *" << endl;
- cout << "* Usage:NumberOperatorNumber= *" << endl;
- cout << "* *" << endl;
- cout << "**********************************" << endl;
- }else{
- cout << "**********************************" << endl;
- cout << "* *" << endl;
- cout << "* Please input: expression *" << endl;
- cout << "* Usage:NumberOperatorNumber= *" << endl;
- cout << "* *" << endl;
- cout << "* If you want to exit. *" << endl;
- cout << "* Usage: Byebye or byebye *" << endl;
- cout << "* *" << endl;
- cout << "**********************************" << endl;
- }
- }
运行结果:
此文章来自于【http://blog.csdn.net/ouyangshima/article/details/8981824】