加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > 学习资料

一个很实用的服务端和客户端进行TCP通信的实例

时间:2021-03-21 21:04:31  来源:  作者:
本文给出一个很实用的服务端和客户端进行TCP通信的小例子。具体实现上非常简单,只是平时编写类似程序,具体步骤经常忘记,还要总是查,暂且将其记下来,方便以后参考。
(1)客户端程序,编写一个文件client.c,内容如下:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <netdb.h>  /* netdb is necessary for struct hostent */
  9.  
  10. #define PORT 4321   /* server port */
  11.  
  12. #define MAXDATASIZE 100
  13.  
  14. int main(int argc, char *argv[])
  15. {
  16.     int sockfd, num;    /* files descriptors */
  17.     char buf[MAXDATASIZE];    /* buf will store received text */
  18.     struct hostent *he;    /* structure that will get information about remote host */
  19.     struct sockaddr_in server;
  20.    
  21.     if (argc != 2)
  22.     {
  23.         printf("Usage: %s <IP Address>\n",argv[0]);
  24.         exit(1);
  25.     }
  26.    
  27.     if((he=gethostbyname(argv[1]))==NULL)
  28.     {
  29.         printf("gethostbyname() error\n");
  30.         exit(1);
  31.     }
  32.    
  33.     if((sockfd=socket(AF_INET,SOCK_STREAM, 0))==-1)
  34.     {
  35.         printf("socket() error\n");
  36.         exit(1);
  37.     }
  38.     bzero(&server,sizeof(server));
  39.     server.sin_family = AF_INET;
  40.     server.sin_port = htons(PORT);
  41.     server.sin_addr = *((struct in_addr *)he->h_addr);
  42.     if(connect(sockfd, (struct sockaddr *)&server, sizeof(server))==-1)
  43.     {
  44.         printf("connect() error\n");
  45.         exit(1);
  46.     }
  47.   
  48.   char str[] = "horst\n"
  49.  
  50.     if((num=send(sockfd,str,sizeof(str),0))==-1){
  51.         printf("send() error\n");
  52.         exit(1);
  53.     }
  54.     if((num=recv(sockfd,buf,MAXDATASIZE,0))==-1)
  55.     {
  56.         printf("recv() error\n");
  57.         exit(1);
  58.     }
  59.     buf[num-1]='\0';
  60.     printf("server message: %s\n",buf);
  61.     close(sockfd);
  62.     return 0;
  63. }
复制代码
(2)服务器端,编写server.c,内容如下
  1. #include <sys/time.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10.  
  11. #define PORT 4321
  12.  
  13. #define BACKLOG 1
  14. #define MAXRECVLEN 1024
  15.  
  16. int main(int argc, char *argv[])
  17. {
  18.     char buf[MAXRECVLEN];
  19.     int listenfd, connectfd;   /* socket descriptors */
  20.     struct sockaddr_in server; /* server's address information */
  21.     struct sockaddr_in client; /* client's address information */
  22.     socklen_t addrlen;
  23.     /* Create TCP socket */
  24.     if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  25.     {
  26.         /* handle exception */
  27.         perror("socket() error. Failed to initiate a socket");
  28.         exit(1);
  29.     }
  30.  
  31.     /* set socket option */
  32.     int opt = SO_REUSEADDR;
  33.     setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  34.  
  35.     bzero(&server, sizeof(server));
  36.  
  37.     server.sin_family = AF_INET;
  38.     server.sin_port = htons(PORT);
  39.     server.sin_addr.s_addr = htonl(INADDR_ANY);
  40.     if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)
  41.     {
  42.         /* handle exception */
  43.         perror("Bind() error.");
  44.         exit(1);
  45.     }
  46.    
  47.     if(listen(listenfd, BACKLOG) == -1)
  48.     {
  49.         perror("listen() error. \n");
  50.         exit(1);
  51.     }
  52.  
  53.     addrlen = sizeof(client);
  54.     while(1){
  55.         if((connectfd=accept(listenfd,(struct sockaddr *)&client, &addrlen))==-1)
  56.            {
  57.             perror("accept() error. \n");
  58.             exit(1);
  59.            }
  60.  
  61.         struct timeval tv;
  62.         gettimeofday(&tv, NULL);
  63.            printf("You got a connection from client's ip %s, port %d at time %ld.%ld\n",inet_ntoa(client.sin_addr),htons(client.sin_port), tv.tv_sec,tv.tv_usec);
  64.         
  65.         int iret=-1;
  66.         while(1)
  67.         {
  68.             iret = recv(connectfd, buf, MAXRECVLEN, 0);
  69.             if(iret>0)
  70.             {
  71.                 printf("%s\n", buf);
  72.             }else
  73.             {
  74.                 close(connectfd);
  75.                 break;
  76.             }
  77.             /* print client's ip and port */
  78.             send(connectfd, buf, iret, 0); /* send to the client welcome message */
  79.         }
  80.     }
  81.     close(listenfd); /* close listenfd */
  82.     return 0;
  83. }
复制代码
 
(3)编译运行
以上两个程序放在同一个目录下,比如 /home/horstxu/Cprog/tcpCSmodel
命令行进入该目录 $ cd /home/horstxu/Cprog/tcpCSmodel
命令行执行 $ gcc -o client client.c ,可以编译出客户端程序。
命令行执行 $ gcc -o server server.c,可以编译出服务端程序。
命令行执行 $ ./server,启动server程序。
这时你可能需要重新打开一个命令行窗口,到刚才的目录下,执行 $ ./client 127.0.0.1,启动客户端程序,就可以看到结果了。
客户端:
  1. $ ./client 127.0.0.1
  2.  
  3. server message:horst
复制代码
 
服务器端:
  1. $./server
  2. you got a connection from client`s ip 127.0.0.1, port 60865 at time 1418281267.643428
复制代码
本程序客户端会自动退出,服务器不会,因此如果想停掉服务器程序,直接在命令行界面按键盘Ctrl+C停止。
程序实现的功能很简单,就是服务器监听4321端口,客户端与之建立TCP连接后,再发送字符串“horst\n”到服务端,服务端打印出来,然后再把字符串传回给客户端,客户端再打印出来。然后客户端关闭连接退出,而服务端继续监听4321端口等待下一次连接。



 
 
 
服务端启动,客户端通过ip地址连接服务端,然后输入要发送的文件名,发送文件到服务段.
  1. /*client.c*/
  2. #include<netinet/in.h>                         // for sockaddr_in  
  3. #include<sys/types.h>                          // for socket  
  4. #include<sys/socket.h>                         // for socket  
  5. #include<stdio.h>                              // for printf  
  6. #include<stdlib.h>                             // for exit  
  7. #include<string.h>                             // for bzero  
  8.  
  9. #define HELLO_WORLD_SERVER_PORT       6666  
  10. #define BUFFER_SIZE                   1024  
  11. #define FILE_NAME_MAX_SIZE            512  
  12.  
  13. int main(int argc, char **argv)  
  14. {  
  15.     if (argc != 2)  
  16.     {  
  17.         printf("Usage: ./%s ServerIPAddress\n", argv[0]);  
  18.         exit(1);  
  19.     }  
  20.  
  21.     // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
  22.     struct sockaddr_in client_addr;  
  23.     bzero(&client_addr, sizeof(client_addr));  
  24.     client_addr.sin_family = AF_INET; // internet协议族  
  25.     client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
  26.     client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口  
  27.  
  28.     // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket  
  29.     int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
  30.     if (client_socket < 0)  
  31.     {  
  32.         printf("Create Socket Failed!\n");  
  33.         exit(1);  
  34.     }  
  35.  
  36.     // 把客户端的socket和客户端的socket地址结构绑定   
  37.     if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
  38.     {  
  39.         printf("Client Bind Port Failed!\n");  
  40.         exit(1);  
  41.     }  
  42.  
  43.     // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
  44.     struct sockaddr_in  server_addr;  
  45.     bzero(&server_addr, sizeof(server_addr));  
  46.     server_addr.sin_family = AF_INET;  
  47.  
  48.     // 服务器的IP地址来自程序的参数   
  49.     if (inet_aton(argv[1], &server_addr.sin_addr) == 0)  
  50.     {  
  51.         printf("Server IP Address Error!\n");  
  52.         exit(1);  
  53.     }  
  54.  
  55.     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
  56.     socklen_t server_addr_length = sizeof(server_addr);  
  57.  
  58.     // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
  59.     if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
  60.     {  
  61.         printf("Can Not Connect To %s!\n", argv[1]);  
  62.         exit(1);  
  63.     }  
  64.  
  65.     char file_name[FILE_NAME_MAX_SIZE + 1];  
  66.     bzero(file_name, sizeof(file_name));  
  67.     printf("Please Input File Name On Server.\t");  
  68.     scanf("%s", file_name);  
  69.  
  70.     char buffer[BUFFER_SIZE];  
  71.     bzero(buffer, sizeof(buffer));  
  72.     strncpy(buffer, file_name, strlen(file_name) > BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));  
  73.     // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件的名字  
  74.     send(client_socket, buffer, BUFFER_SIZE, 0);  
  75.  
  76.     FILE *fp = fopen(file_name, "w");  
  77.     if (fp == NULL)  
  78.     {  
  79.         printf("File:\t%s Can Not Open To Write!\n", file_name);  
  80.         exit(1);  
  81.     }  
  82.  
  83.     // 从服务器端接收数据到buffer中   
  84.     bzero(buffer, sizeof(buffer));  
  85.     int length = 0;  
  86.     while(length = recv(client_socket, buffer, BUFFER_SIZE, 0))  
  87.     {  
  88.         if (length < 0)  
  89.         {  
  90.             printf("Recieve Data From Server %s Failed!\n", argv[1]);  
  91.             break;  
  92.         }  
  93.  
  94.         int write_length = fwrite(buffer, sizeof(char), length, fp);  
  95.         if (write_length < length)  
  96.         {  
  97.             printf("File:\t%s Write Failed!\n", file_name);  
  98.             break;  
  99.         }  
  100.         bzero(buffer, BUFFER_SIZE);  
  101.     }  
  102.  
  103.     printf("Recieve File:\t %s From Server[%s] Finished!\n", file_name, argv[1]);  
  104.  
  105.     // 传输完毕,关闭socket   
  106.     fclose(fp);  
  107.     close(client_socket);  
  108.     return 0;  
  109.  
  110. }  
  111.  
  112.  
复制代码
  1. /*server.c*/
  2. #include<netinet/in.h>
  3. #include<sys/types.h>
  4. #include<sys/socket.h>
  5. #include<stdio.h>
  6. #include<stdlib.h>
  7. #include<string.h>
  8.  
  9. #define HELLO_WORLD_SERVER_PORT    6666         //端口号
  10. #define LENGTH_OF_LISTEN_QUEUE     20
  11. #define BUFFER_SIZE                1024
  12. #define FILE_NAME_MAX_SIZE         512
  13.  
  14. int main(int argc, char **argv)
  15. {
  16.     // set socket's address information
  17.     // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口
  18.     struct sockaddr_in   server_addr;
  19.     bzero(&server_addr, sizeof(server_addr));
  20.     server_addr.sin_family = AF_INET;
  21.     server_addr.sin_addr.s_addr = htons(INADDR_ANY);
  22.     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
  23.  
  24.     // create a stream socket
  25.     // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口
  26.     int server_socket = socket(PF_INET, SOCK_STREAM, 0);
  27.     if (server_socket < 0)
  28.     {
  29.         printf("Create Socket Failed!\n");
  30.         exit(1);
  31.     }
  32.  
  33.     // 把socket和socket地址结构绑定
  34.     if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))
  35.     {
  36.         printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);
  37.         exit(1);
  38.     }
  39.  
  40.     // server_socket用于监听
  41.     if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))
  42.     {
  43.         printf("Server Listen Failed!\n");
  44.         exit(1);
  45.     }
  46.  
  47.     // 服务器端一直运行用以持续为客户端提供服务
  48.     while(1)
  49.     {
  50.         // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept
  51.         // 接受此请求,同时将client端的地址和端口等信息写入client_addr中
  52.         struct sockaddr_in client_addr;
  53.         socklen_t          length = sizeof(client_addr);
  54.  
  55.         // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中
  56.         // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以
  57.         // 用select()来实现超时检测
  58.         // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信
  59.         // 这里的new_server_socket代表了这个通信通道
  60.         int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);
  61.         if (new_server_socket < 0)
  62.         {
  63.             printf("Server Accept Failed!\n");
  64.             break;
  65.         }
  66.  
  67.         char buffer[BUFFER_SIZE];
  68.         bzero(buffer, sizeof(buffer));
  69.         length = recv(new_server_socket, buffer, BUFFER_SIZE, 0);
  70.         if (length < 0)
  71.         {
  72.             printf("Server Recieve Data Failed!\n");
  73.             break;
  74.         }
  75.  
  76.         char file_name[FILE_NAME_MAX_SIZE + 1];
  77.         bzero(file_name, sizeof(file_name));
  78.         strncpy(file_name, buffer,
  79.                 strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
  80.  
  81.         FILE *fp = fopen(file_name, "r");
  82.         if (fp == NULL)
  83.         {
  84.             printf("File:\t%s Not Found!\n", file_name);
  85.         }
  86.         else
  87.         {
  88.             bzero(buffer, BUFFER_SIZE);
  89.             int file_block_length = 0;
  90.             while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
  91.             {
  92.                 printf("file_block_length = %d\n", file_block_length);
  93.  
  94.                 // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端
  95.                 if (send(new_server_socket, buffer, file_block_length, 0) < 0)
  96.                 {
  97.                     printf("Send File:\t%s Failed!\n", file_name);
  98.                     break;
  99.                 }
  100.  
  101.                 bzero(buffer, sizeof(buffer));
  102.             }
  103.             fclose(fp);
  104.             printf("File:\t%s Transfer Finished!\n", file_name);
  105.         }
  106.  
  107.         close(new_server_socket);
  108.     }
  109.  
  110.     close(server_socket);
  111.  
  112.     return 0;
  113. }
  114.  
  115.  
复制代码

 
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
实现php间隔一段时间执行一次某段代码
实现php间隔一段时间
相关文章
    无相关信息
栏目更新
栏目热门