基本的TCP socket编程示例 -- 时间服务器及客户端


服务器端的编写

    1.  使用socket函数新建一个套接字,指定其 协议族family(AF_INET)、协议类型type(SOCK_STREAM)、协议(0, 系统根据family和type指定默认值)

    2.  使用bind函数将本地协议地址绑定到套接字上,

    3.  使用listen函数监听客户端发来的请求

    4.  使用accept函数循环接受客户端的请求

    5.  使用send和recv函数发送和接收数据 

 

客户端程序的编写

     1.  使用socket函数创建一个套接字

     2.  使用connect函数连接服务器

     3.  使用send和recv发送和接受数据

 

示例如下:

 由于使用winsock之前需要初始化winsock DLL,所以我将winsock的初始化和释放封装到了一个类中,如下:

  1 // 初始化winsock

 2  #include <winsock2.h>
 3 #include <iostream>
 4  class SockInitializer{
 5      public:
 6         SockInitializer()
 7         {
 8             WORD versionRequired = MAKEWORD( 22);
 9             WSADATA wsaData;
10              int ret = WSAStartup(versionRequired, &wsaData);
11              if ( 0 != ret){
12                 std::cerr <<  " socket initialize failed ";
13                 exit( 1);
14             }
15         }
16         ~SockInitializer(){
17             WSACleanup();
18         }
19 };

 

接下来是服务器端的编写:

注:关于listen的第二个参数backlog,我们可以为其指定一个环境变量,以随时调整它的值 

 1  //  服务器端程序
 2  #include <winsock2.h>
 3 #include <cstdio>
 4 #include <ctime>
 5 
 6  using  namespace std;
 7 
 8 SockInitializer sockInitializer;    //  初始化winsock
 9 
10  int main()
11 {
12     SOCKET listenfd, connfd;
13     sockaddr_in serverAddr;
14     
15      char buf[ 100];
16     memset(buf,  0sizeof(buf));
17 
18      //  1. 建立一个socket
19      listenfd = socket(AF_INET, SOCK_STREAM,  0); 
20      if (INVALID_SOCKET == listenfd){
21         cerr <<  " invalid socket ";
22         exit( 1);
23     }
24 
25      //  2. 绑定到本地的端口
26      serverAddr.sin_family = AF_INET;
27     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);   //  使用通配地址
28      serverAddr.sin_port = htons( 13);                  //  13是时间服务器的端口号
29 
30      int ret = bind(listenfd, (sockaddr*)&serverAddr,  sizeof(serverAddr) );
31      if (ret !=  0){
32         cerr <<  " error on bind: " << WSAGetLastError();
33         exit( 1);
34     }
35 
36      //  3. 开始监听客户端请求
37      listen(listenfd, SOMAXCONN);   //  listen的第二个参数指定了套接字排队的最大连接个数,
38                                     //  我们为其指定 SOMAXCONN ,表示系统支持的最大连接个数
39       //  4. 循环接受客户端的请求
40       while ( true){
41         cout <<  " accept ... " << endl;
42         connfd = accept(listenfd, (sockaddr*)NULL, NULL);   //  这里我们不需要接受客户端的sockaddr, 因此指定为NULL
43           if (INVALID_SOCKET == connfd){
44             cerr <<  " error on accept: " << WSAGetLastError() << endl;
45              continue;
46         }
47         cout <<  " successfully accept socket: " << connfd << endl;
48         time_t ticks = time(NULL);
49         snprintf(buf,  sizeof(buf),  " %.24s\r\n ", ctime(&ticks) );
50         send(connfd, buf, strlen(buf),  0 );
51 
52         closesocket(connfd);
53     }
54 } 

  

客户端程序:

  1 // 客户端程序

 2  #include <winsock2.h>
 3 #include <cstdio>
 4 #include <iostream>
 5 
 6  using  namespace std;
 7 
 8 SockInitializer sockInitializer;  //  初始化winsock
 9 
10  int main( int argc,  char **argv)
11 {
12      if (argc !=  2){
13         cerr <<  " usage: client <ipaddress> ";
14         exit( 1);
15     }
16 
17      //  1. 创建套接字
18      SOCKET sockfd = socket(AF_INET, SOCK_STREAM,  0);
19      if (sockfd == INVALID_SOCKET){
20         cerr <<  " invalid socket ";
21         exit( 1);
22     }
23 
24      //  2. 连接至服务器
25      sockaddr_in serverAddr;
26     memset(&serverAddr,  0sizeof serverAddr);
27     serverAddr.sin_family = AF_INET;
28     serverAddr.sin_port = htons( 13);
29     serverAddr.sin_addr.s_addr = inet_addr(argv[ 1]);
30 
31      int ret = connect(sockfd, (SOCKADDR*)&serverAddr,  sizeof serverAddr);   //  指定服务器的地址
32       if ( 0 != ret){
33         cout <<  " error on connect: " << WSAGetLastError();
34         exit( 1);
35     }
36 
37      //  3. 接受数据
38       char buf[ 100];
39      int n;
40      while (  0 != (n = recv(sockfd, buf,  sizeof buf,  0) ) ){
41         buf[n] =  ' \0 ';
42         cout << buf;
43     }
44 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM