[C++] Windows下的socket编程(这是一个简单的TCP/IP例子)

Socket的概念:

Socket,即套接字,用于描述地址和端口,是一个通信链的句柄。

应用程序通过Socket像网络发出请求或者回应。


什么事客户/服务器模式:

在TCP/IP网络应用中,通信的两个进程相互作用的主要模式是客户/服务器模式,即客户端向服务器发出请求,服务器接收请求后,提供相应的服务。客户/服务器模式的建立基于以下两点:

1:建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用

2:网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区

因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务端模式的TCP/IP

(这部分内容摘自socket编程原理)


需要做什么:

客户端:建立Socket,通过端口号和地址确定目标服务器,使用Connect连接到服务器,send发送消息,等待处理,通信完成后调用CloseSocket关闭Socket

服务端:建立Socket,声明自身的端口号和地址并绑定到Socket,使用Listen打开监听,然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容,通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket

代码示例

客户端:这里创建一个CLientNet类,用于表示一个客户

[cpp]  view plain  copy
  1. #pragma once  
  2.   
  3. /* 
  4. ClinetNet.h: 
  5. 用于表示一个客户的网络操作 
  6. */  
  7.   
  8. #include <stdio.h>  
  9. #include<windows.h>  
  10.   
  11. #pragma comment(lib, "Ws2_32.lib")  
  12.   
  13. class CClientNet  
  14. {  
  15. public:  
  16.     //连接上指定服务器  
  17.     int Connect(int port,const char* address);  
  18.     //发送信息  
  19.     int SendMsg(const char* msg,int len);  
  20.     //关闭  
  21.     void Close();  
  22.   
  23. private:  
  24.     SOCKET m_sock;  
  25. };  

[cpp]  view plain  copy
  1. /* 
  2. CLientNet.cpp 
  3. */  
  4. #include "ClientNet.h"  
  5.   
  6.   
  7. int CClientNet::Connect( int port,const char* address )  
  8. {  
  9.     int rlt = 0;  
  10.   
  11.     //用于记录错误信息并输出  
  12.     int iErrMsg;  
  13.     //启动WinSock  
  14.     WSAData wsaData;  
  15.     iErrMsg = WSAStartup(MAKEWORD(1,1),&wsaData);  
  16.     if (iErrMsg != NO_ERROR)  
  17.         //有错误  
  18.     {  
  19.         printf("failed with wsaStartup error : %d\n",iErrMsg);  
  20.   
  21.         rlt = 1;  
  22.         return rlt;  
  23.     }  
  24.   
  25.     //创建Socket  
  26.     m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
  27.     if (m_sock == INVALID_SOCKET)  
  28.         //创建Socket失败  
  29.     {  
  30.         printf("socket failed with error : %d\n",WSAGetLastError());  
  31.   
  32.         rlt = 2;  
  33.         return rlt;  
  34.     }  
  35.   
  36.     //目标服务器数据  
  37.     sockaddr_in sockaddrServer;  
  38.     sockaddrServer.sin_family = AF_INET;  
  39.     sockaddrServer.sin_port = port;  
  40.     sockaddrServer.sin_addr.s_addr = inet_addr(address);  
  41.   
  42.     //连接,sock与目标服务器连接  
  43.     iErrMsg = connect(m_sock,(sockaddr*)&sockaddrServer,sizeof(sockaddrServer));  
  44.     if (iErrMsg < 0)  
  45.     {  
  46.         printf("connect failed with error : %d\n",iErrMsg);  
  47.   
  48.         rlt = 3;  
  49.         return rlt;  
  50.     }  
  51.   
  52.     return rlt;  
  53. }  
  54.   
  55.   
  56.   
  57.   
  58. int CClientNet::SendMsg(const char* msg,int len)  
  59. {  
  60.     int rlt = 0;  
  61.   
  62.     int iErrMsg = 0;  
  63.   
  64.     //发送消息,指定sock发送消息  
  65.     iErrMsg = send(m_sock,msg,len,0);  
  66.     if (iErrMsg < 0)  
  67.         //发送失败  
  68.     {  
  69.         printf("send msg failed with error : %d\n",iErrMsg);  
  70.   
  71.         rlt = 1;  
  72.         return rlt;  
  73.     }  
  74.   
  75.     return rlt;  
  76. }  
  77.   
  78. void CClientNet::Close()  
  79. {  
  80.     closesocket(m_sock);  
  81. }  

[cpp]  view plain  copy
  1. #include "ClientNet.h"  
  2.   
  3. void main()  
  4. {  
  5.     CClientNet client;  
  6.       
  7.     //连接到127.0.0.1(即本地),端口号为8888的服务端  
  8.     printf("Connect\n");  
  9.     client.Connect(8888,"127.0.0.1");  
  10.       
  11.     //发送消息  
  12.     printf("send msg\n");  
  13.     client.SendMsg("hello\0",sizeof("hello\0"));  
  14.       
  15.     //关闭socket  
  16.     printf("close\n");  
  17.     client.Close();  
  18.   
  19.     system("pause");  
  20. }  


服务端代码:

[cpp]  view plain  copy
  1. #pragma once  
  2.   
  3. /* 
  4. ServerNet.h 
  5. 用于表示服务端的网络操作 
  6.  
  7. */  
  8.   
  9. #include <stdio.h>  
  10. #include <winsock.h>  
  11.   
  12. #pragma comment (lib,"ws2_32.lib")  
  13.   
  14. class CServerNet  
  15. {  
  16. public:  
  17.   
  18.     //初始化服务器,返回0表示成功  
  19.     int Init(const char* address,int port);  
  20.   
  21.     //更新数据  
  22.     void Run();  
  23.   
  24.   
  25. private:  
  26.     SOCKET m_sock;  
  27. };  

[cpp]  view plain  copy
  1. /* 
  2. ServerNet.cpp 
  3. */  
  4. #include "ServerNet.h"  
  5.   
  6. int CServerNet::Init( const char* address,int port )  
  7. {  
  8.     int rlt = 0;  
  9.   
  10.     //用于记录错误信息,并输出  
  11.     int iErrorMsg;  
  12.   
  13.     //初始化WinSock  
  14.     WSAData wsaData;  
  15.     iErrorMsg = WSAStartup(MAKEWORD(1,1),&wsaData);  
  16.       
  17.     if (iErrorMsg != NO_ERROR)  
  18.     {  
  19.         //初始化WinSock失败  
  20.         printf("wsastartup failed with error : %d\n",iErrorMsg);  
  21.   
  22.         rlt = 1;  
  23.         return rlt;  
  24.     }  
  25.   
  26.     //创建服务端Socket  
  27.     m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
  28.     if (m_sock == INVALID_SOCKET)  
  29.           
  30.     {  
  31.         //创建Socket异常  
  32.         printf("socket failed with error : %d\n",WSAGetLastError());  
  33.   
  34.         rlt = 2;  
  35.         return rlt;  
  36.     }  
  37.   
  38.     //声明信息  
  39.     sockaddr_in serverAddr;  
  40.     serverAddr.sin_family = AF_INET;  
  41.     serverAddr.sin_port = port;  
  42.     serverAddr.sin_addr.s_addr = inet_addr(address);  
  43.   
  44.     //绑定  
  45.     iErrorMsg = bind(m_sock,(sockaddr*)&serverAddr,sizeof(serverAddr));  
  46.     if (iErrorMsg < 0)  
  47.     {  
  48.         //绑定失败  
  49.         printf("bind failed with error : %d\n",iErrorMsg);  
  50.         rlt = 3;  
  51.         return rlt;  
  52.     }  
  53.   
  54.       
  55.   
  56.     return rlt;  
  57. }  
  58.   
  59. void CServerNet::Run()  
  60. {  
  61.     //公开连接  
  62.     listen(m_sock,5);  
  63.   
  64.     sockaddr_in tcpAddr;  
  65.     int len = sizeof(sockaddr);  
  66.     SOCKET newSocket;  
  67.     char buf[1024];  
  68.     int rval;  
  69.   
  70.     do   
  71.     {  
  72.         //接收信息  
  73.         newSocket = accept(m_sock,(sockaddr*)&tcpAddr,&len);  
  74.   
  75.           
  76.         if (newSocket == INVALID_SOCKET)  
  77.         {  
  78.             //非可用socket  
  79.   
  80.         }  
  81.         else  
  82.         {  
  83.             //新socket连接  
  84.             printf("new socket connect : %d\n",newSocket);  
  85.   
  86.   
  87.             //消息处理  
  88.             do  
  89.             {  
  90.                 printf("process\n");  
  91.                 //接收数据  
  92.                 memset(buf,0,sizeof(buf));  
  93.                 rval = recv(newSocket,buf,1024,0);  
  94.   
  95.                   
  96.                 if (rval == SOCKET_ERROR)  
  97.                     //这应该是个异常,当客户端没有调用closeSocket就直接退出游戏的时候,将会进入这里  
  98.                     printf("recv socket error\n");  
  99.   
  100.                   
  101.                   
  102.                 if (rval == 0)  
  103.                     //recv返回0表示正常退出  
  104.                     printf("ending connection");  
  105.                 else  
  106.                     //显示接收到的数据  
  107.                     printf("recv %s\n",buf);  
  108.   
  109.   
  110.             }while(rval != 0);  
  111.   
  112.             //关闭对应Accept的socket  
  113.             closesocket(newSocket);  
  114.         }  
  115.           
  116.   
  117.           
  118.     } while (1);  
  119.   
  120.     //关闭自身的Socket  
  121.     closesocket(m_sock);  
  122. }  


[cpp]  view plain  copy
  1. #include "ServerNet.h"  
  2.   
  3. int main(int argc, char **argv)  
  4. {  
  5.     CServerNet serverNet;  
  6.     int iRlt = serverNet.Init("127.0.0.1",8888);  
  7.     if (iRlt == 0)  
  8.     {  
  9.         printf("init ok...\n");  
  10.         serverNet.Run();  
  11.     }  
  12.     else  
  13.         printf("serverNet init failed with error : %d\n",iRlt);  
  14.     system("pause");  
  15. }  

  博客地址:http://blog.csdn.net/xv_ly15/article/details/8955188
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值