Socket 服务器 客户端 多线程 异步例程

 

下面这个是客户端的头文件,解释够清楚把

   1: #pragma once

   2:

   3: typedef void (*CallFun_Client) (LPVOID/*传递值*/,int/*代码*/,char*/*数据*/);/*回调函数指针*/

   4:

   5: class CClientSocket

   6: {

   7: public:

   8:     CClientSocket();//构造函数

   9:     ~CClientSocket();//析构函数

  10:     BOOL Initialize(CallFun_Client call/*回调函数*/,LPVOID lpParameter/*传递值*/);//初始化

  11:     int Send(char* chBuf/*发送给服务器的数据*/);//发送

  12:     BOOL Connect(char* chAddr/*服务器IP*/, int nPort/*服务器端口*/);//连接服务器

  13:     BOOL Close();//关闭连接

  14: public:

  15:     SOCKET m_hSock;//Socket句柄

  16:     CallFun_Client m_pCall;//回调函数指针

  17:     LPVOID m_lpParameter;//传递值

  18:     HANDLE m_hThread;//线程句柄

  19: };

下面是它的实现文件

构造函数,调用 2.2版本的Socket库

   1: CClientSocket::CClientSocket()

   2: {

   3:     WSADATA wsaData;

   4:     WSAStartup(MAKEWORD(2,2),&wsaData);

   5: }

析构

   1: CClientSocket::~CClientSocket()

   2: {

   3:     closesocket(m_hSock);//关闭Socket句柄

   4:     WSACleanup();//释放Socket

   5:     CloseHandle(m_hThread);//关闭线程句柄

   6: }

初始化.关闭 Initialize Close

   1: BOOL CClientSocket::Initialize(CallFun_Client call,LPVOID lpParameter)

   2: {

   3:     m_pCall=call;

   4:     m_lpParameter=lpParameter;

   5:     return TRUE;

   6: }

   7: BOOL CClientSocket::Close()

   8: {

   9:     if(closesocket(m_hSock)!=0)

  10:         return FALSE;

  11:     CloseHandle(m_hThread);

  12:     m_hSock=0;

  13:     m_hThread=0;

  14:     return TRUE;

  15: }

客户端发送 Send

   1: int CClientSocket::Send(char* chBuf)

   2: {

   3:     return send(m_hSock,chBuf,strlen(chBuf),0);

   4: }

连接服务器  Connect

   1: BOOL CClientSocket::Connect(char* chAddr, int nPort)

   2: {

   3:     int nError;

   4:     m_hSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建套接字

   5:     SOCKADDR_IN addrSrv;

   6:     addrSrv.sin_addr.S_un.S_addr=inet_addr(chAddr);//服务器的IP

   7:     addrSrv.sin_family=AF_INET;

   8:     addrSrv.sin_port=htons(nPort);//服务器的端口

   9:     nError=connect(m_hSock,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//连接

  10:     if(!nError)

  11:         return FALSE;

  12:     m_hThread=CreateThread(NULL,0,ThreadProc_Client,this,0,NULL);//启动线程

  13:     return TRUE;

  14: }

线程处理:

   1: DWORD _stdcall ThreadProc_Client(LPVOID lpParameter)

   2: {

   3:     CClientSocket* pClient=(CClientSocket*)lpParameter;

   4:     int nError;

   5:     while (true)

   6:     {

   7:         char chBuf[1024]={};

   8:         nError=recv(pClient->m_hSock,chBuf,sizeof(chBuf),0);//接受

   9:         if(nError<=0)//如果返回<= 的数,就证明已经断开服务器,或者Socket关闭

  10:         {

  11:             pClient->m_pCall(pClient->m_lpParameter,-1,NULL);//-1代表断开服务器

  12:             break;//跳出循环

  13:         }

  14:         pClient->m_pCall(pClient->m_lpParameter,1,chBuf);//通过回调函数,告诉数据,代码1表示收到数据

  15:     }

  16:     return TRUE;

  17: }

客户端完毕

服务器的头文件:

   1: #pragma once

   2:

   3: typedef void (*CallFun_Sever) (LPVOID/*传递值*/,SOCKET/*客户端Socket句柄*/,int/*代码*/,char*/*数据*/);/*回调函数指针*/

   4:

   5: class CSeverSocket

   6: {

   7: public:

   8:     CSeverSocket(void);

   9:     ~CSeverSocket(void);

  10:     BOOL Initialize(CallFun_Sever call/*回调函数*/,LPVOID lpParameter/*传递值*/);//初始化

  11:     BOOL Close();//停止服务器

  12:     BOOL Start(int nPort);//启动服务器

  13:     int Send(SOCKET ClientSock/*客户端Socket*/,char* chBuf/*数据*/);//发送数据给客户端

  14:

  15: public:

  16:     SOCKET m_hSock;//Socket句柄

  17:     CallFun_Sever m_pCall;//回调函数指针

  18:     LPVOID m_lpParameter;//传递值

  19:     HANDLE m_hThread;//线程句柄

  20: };

实现文件,构造函数,析构函数,Initialize,Close都和客户端差不多

Send 发送

   1: int CSeverSocket::Send(SOCKET ClientSock,char* chBuf)

   2: {

   3:     return send(ClientSock,chBuf,strlen(chBuf),0);

   4: }

Start 启动服务器

   1: BOOL CSeverSocket::Start(int nPort)

   2: {

   3:     m_hSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建套接字

   4:     SOCKADDR_IN addrSrv;

   5:     addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

   6:     addrSrv.sin_family=AF_INET;

   7:     addrSrv.sin_port=htons(nPort);

   8:     if(bind(m_hSock,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))!=0)//给未命名套接字赋一个本地名

   9:         return FALSE;

  10:     if(listen(m_hSock,1)!=0)//在指定套接字上监听外来连接

  11:         return FALSE;

  12:     m_hThread=CreateThread(NULL,0,ThreadProc_Sever,this,0,NULL);//启动线程

  13:     return TRUE;

  14: }

线程处理:

   1: DWORD _stdcall ThreadProc_Sever(LPVOID lpParameter)

   2: {

   3:     CSeverSocket* pSever=(CSeverSocket*)lpParameter;

   4:     fd_set fdSocket;

   5:     FD_ZERO(&fdSocket);

   6:     FD_SET(pSever->m_hSock,&fdSocket);

   7:     while (true)

   8:     {

   9:         fd_set fdRead=fdSocket;

  10:         if(select(0,&fdRead,NULL,NULL,NULL)<=0)

  11:             break;

  12:         for(int i=0; i<(int)fdSocket.fd_count; i++)

  13:         {

  14:             if(!FD_ISSET(fdSocket.fd_array[i],&fdRead))

  15:                 continue;

  16:             if(fdSocket.fd_array[i]==pSever->m_hSock)

  17:             {

  18:                 //来新的客户

  19:                 sockaddr_in addrRemote;

  20:                 int nAddrLen=sizeof(addrRemote);

  21:                 SOCKET sNew=accept(pSever->m_hSock,(SOCKADDR*)&addrRemote, &nAddrLen);

  22:                 pSever->m_pCall(pSever->m_lpParameter,sNew,0,NULL);

  23:                 FD_SET(sNew,&fdSocket);

  24:             }

  25:             else

  26:             {

  27:                 void* chBuf[1024];

  28:                 memset(chBuf,0x00,sizeof(chBuf)/sizeof(chBuf[0]));

  29:                 if(recv(fdSocket.fd_array[i],(char*)chBuf,sizeof(chBuf)/sizeof(chBuf[0]),0)>0)

  30:                 {

  31:                     //收到新数据

  32:                     pSever->m_pCall(pSever->m_lpParameter,fdSocket.fd_array[i],1,(char*)chBuf);

  33:                 }

  34:                 else

  35:                 {

  36:                     //客户断开服务器

  37:                     closesocket(fdSocket.fd_array[i]);

  38:                     pSever->m_pCall(pSever->m_lpParameter,fdSocket.fd_array[i],-1,NULL);

  39:                     FD_CLR(fdSocket.fd_array[i], &fdSocket);

  40:                 }

  41:             }

  42:         }

  43:

  44:     }

  45:     return TRUE;

  46: }

源码下载,有什么缺陷什么的希望大家能提出来,我好改正

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据