基本的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 }

 

posted on 2012-10-20 20:59  sanlo  阅读(3975)  评论(0编辑  收藏  举报