zoukankan      html  css  js  c++  java
  • Linux TCP通信例程

      Linux环境下实现实现简单 TCP通信demo。

    例程一:client端和serve端相互发送接收,打印接收到的内容即退出结束。这里使用的IP地址是本机环回地址“127.0.0.1”,只能进行本地通信。

     1 localhost、127.0.0.1和0.0.0.0和本机IP的区别
     2 localhost
     3 localhost其实是域名,一般windows系统默认将localhost指向127.0.0.1,但是localhost并不等于127.0.0.1,localhost指向的IP地址是可以配置的
     4 
     5 127.0.0.1
     6 首先我们要先知道一个概念,凡是以127开头的IP地址,都是回环地址(Loop back address),其所在的回环接口一般被理解为虚拟网卡,并不是真正的路由器接口。
     7 
     8 所谓的回环地址,通俗的讲,就是我们在主机上发送给127开头的IP地址的数据包会被发送的主机自己接收,根本传不出去,外部设备也无法通过回环地址访问到本机。
     9 
    10 小说明:正常的数据包会从IP层进入链路层,然后发送到网络上;而给回环地址发送数据包,数据包会直接被发送主机的IP层获取,后面就没有链路层他们啥事了。
    11 
    12 而127.0.0.1作为{127}集合中的一员,当然也是个回环地址。只不过127.0.0.1经常被默认配置为localhost的IP地址。
    13 一般会通过ping 127.0.0.1来测试某台机器上的网络设备是否工作正常。
    14 
    15 0.0.0.0
    16 首先,0.0.0.0是不能被ping通的。在服务器中,0.0.0.0并不是一个真实的的IP地址,它表示本机中所有的IPV4地址。监听0.0.0.0的端口,就是监听本机中所有IP的端口。
    17 
    18 本机IP
    19 本机IP通常仅指在同一个局域网内,能同时被外部设备访问和本机访问的那些IP地址(可能不止一个)。像127.0.0.1这种一般是不被当作本机IP的。本机IP是与具体的网络接口绑定的,比如以太网卡、无线网卡或者PPP/PPPoE拨号网络的虚拟网卡,想要正常工作都要绑定一个地址,否则其他设备就不知道如何访问它
    20 
    21 
    22 链接:https://www.jianshu.com/p/ad7cd1d5be45
    IP 小知识

    代码如下:

    client code:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    
    int main(){
        //创建套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
    
        //向服务器(特定的IP和端口)发起请求
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        while (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) {
            sleep(1);
            printf("wait serve
    ");
        }
       
        //读取服务器传回的数据
        char buffer[40];
        read(sock, buffer, sizeof(buffer)-1);
       
        printf("Message form server: %s
    ", buffer);
       
       //向serve端发送数据
        char str[] = "Hello!";
        int count = 0, err;
        while ((err = write(sock, str, sizeof(str))) <= 0 && count++ < 10) {
            printf("wait %d
    ", err);
            sleep(1);
        }
        
       
        //关闭套接字
        close(sock);
    
        return 0;
    }
    client code

    serve code:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    int main(){
        //创建套接字
        int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        //将套接字和IP、端口绑定
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    
        //进入监听状态,等待用户发起请求
        listen(serv_sock, 20);
        printf("监听结束
    ");
        //接收客户端请求
        struct sockaddr_in clnt_addr;
        socklen_t clnt_addr_size = sizeof(clnt_addr);
        int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        
        //向客户端发送数据
        char str[] = "Hello World!";
        write(clnt_sock, str, sizeof(str));
        
        //读取client传回的数据
        char buffer[40];
        int err, count = 0;
        while ( (err = read(clnt_sock, buffer, sizeof(buffer)-1)) <= 0 && count++ < 10) {
            printf("wait %d
    ", err);
            sleep(1);
        }
        
        printf("Message form client: %s
    ", buffer);
       
        //关闭套接字
        close(clnt_sock);
        close(serv_sock);
    
        return 0;
    }
    serve Code

    运行演示效果:

    例程二:client和serve都创建一个线程进行获取输入和发送输入内容,原来主线程会将接收到的内容打印出来,当输入内容或则接收内容为“bye”时将退出程序运行。这里serve是运行在IP地址为"172.16.194.184"的虚拟机上,所以client和serve的对应代码需要修改serve的IP地址。I

    IP地址的查看方法:输入ifconfig指令:

    代码如下:

    client code:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <unistd.h>
      5 #include <arpa/inet.h>
      6 #include <sys/socket.h>
      7 #include <pthread.h>
      8 
      9 
     10 int getchar_input_str(char * input_buff);
     11 
     12 int g_flag_exit = 0;
     13 char input_str[100], read_buff[100];
     14 int clnt_sock_fd;
     15 
     16 
     17 
     18 void * TCP_send(void *arg)
     19 {
     20     int input_count = 0;
     21     
     22     while(1) {
     23         printf("self:");
     24         input_count = getchar_input_str(input_str);
     25         send(clnt_sock_fd, input_str, input_count + 1, 0);
     26         
     27         //printf("client:[%d] %s
    ", input_count, input_str);
     28         if (input_str[0] == 'b' && input_str[1] == 'y' && input_str[2] == 'e') {
     29             g_flag_exit = 1;
     30             
     31             return NULL;
     32         }
     33     }
     34     
     35 }
     36 
     37 
     38 
     39 int main()
     40 {
     41 
     42     //创建套接字
     43     clnt_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
     44 
     45     //向服务器(特定的IP和端口)发起请求
     46     struct sockaddr_in serv_addr;
     47     memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
     48     serv_addr.sin_family = AF_INET;  //使用IPv4地址
     49     serv_addr.sin_addr.s_addr = inet_addr("172.16.194.184");  //具体的IP地址
     50     serv_addr.sin_port = htons(1234);  //端口
     51     
     52     
     53     
     54     while (connect(clnt_sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) {
     55         sleep(1);
     56         printf("wait serve connect
    ");
     57     }
     58     
     59     pthread_t tid;        
     60     pthread_create(&tid, NULL, TCP_send, "TCP_send");
     61     
     62     while(1) {
     63         
     64         recv(clnt_sock_fd, read_buff, sizeof(read_buff)-1, 0);
     65         printf("33[5D");
     66         printf("Message form serve: %s
    self:", read_buff);
     67         fflush(stdout);
     68         if (read_buff[0] == 'b' && read_buff[1] == 'y' && read_buff[2] == 'e') {
     69             printf("exit connect
    ");
     70             //send(clnt_sock_fd, "bye!", 5, 0);
     71             pthread_cancel(tid);
     72             
     73             break;
     74         }
     75         
     76         if (g_flag_exit)
     77             break;
     78     }
     79 
     80     printf("
    ");
     81 
     82     //关闭套接字
     83     close(clnt_sock_fd);
     84 
     85     return 0;
     86 }
     87 
     88 
     89 
     90 
     91 /*
     92  *@brief  通过getchar()获取输入的字符串
     93  *@param  buff:存放输入字符串
     94  *@return count:输入的字符数
     95  * */
     96 int getchar_input_str(char * input_buff)
     97 {
     98     char input_char, count = 0;
     99     
    100     /*获取输入字符*/
    101     while((input_char = getchar()) != '
    '){
    102         input_buff[count] = input_char;
    103         count ++;
    104     }
    105     /*清除键盘输入缓存*/
    106     if(input_char != '
    '){
    107         while(((input_char = getchar()) != '
    ') && (input_char != EOF));
    108     }
    109     /*字符串结尾以‘’结束*/
    110     input_buff[count] = '';
    111     
    112     return count;
    113     
    114 }
    client Code

    serve code:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <unistd.h>
      5 #include <arpa/inet.h>
      6 #include <sys/socket.h>
      7 #include <pthread.h>
      8 
      9 
     10 int getchar_input_str(char * input_buff);
     11 
     12 int g_flag_exit = 0;
     13 char input_str[100], read_buff[100];
     14 int serv_sock_fd;
     15 int clnt_sock_fd;
     16 
     17 
     18 
     19 void * TCP_send(void *arg)
     20 {
     21     int input_count = 0;
     22     
     23     while(1) {
     24         printf("self:");
     25         input_count = getchar_input_str(input_str);
     26         send(clnt_sock_fd, input_str, input_count + 1, 0);
     27         
     28         //printf("serve:[%d] %s
    ", input_count, input_str);
     29         if (input_str[0] == 'b' && input_str[1] == 'y' && input_str[2] == 'e') {
     30             g_flag_exit = 1;
     31             
     32             return NULL;
     33         }
     34     }
     35     
     36 }
     37 
     38 
     39 
     40 int main()
     41 {
     42 
     43     //创建套接字
     44     serv_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
     45 
     46     //向服务器(特定的IP和端口)发起请求
     47     struct sockaddr_in serv_addr;
     48     memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
     49     serv_addr.sin_family = AF_INET;  //使用IPv4地址
     50     serv_addr.sin_addr.s_addr = inet_addr("172.16.194.184");  //具体的IP地址
     51     serv_addr.sin_port = htons(1234);  //端口
     52     
     53     bind(serv_sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
     54 
     55     //进入监听状态,等待用户发起请求
     56     listen(serv_sock_fd, 20);
     57     printf("监听结束
    ");
     58     //接收客户端请求
     59     struct sockaddr_in clnt_addr;
     60     socklen_t clnt_addr_size = sizeof(clnt_addr);
     61     clnt_sock_fd = accept(serv_sock_fd, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
     62     
     63     printf("accept end
    ");
     64     
     65     pthread_t tid;    
     66     pthread_create(&tid, NULL, TCP_send, "TCP_send");
     67     
     68     while(1) {
     69         recv(clnt_sock_fd, read_buff, sizeof(read_buff)-1, 0);
     70         printf("33[5D");
     71         printf("Message form client: %s
    self:", read_buff);
     72         fflush(stdout);
     73         if (read_buff[0] == 'b' && read_buff[1] == 'y' && read_buff[2] == 'e') {
     74             printf("exit connect
    ");
     75             //send(clnt_sock_fd, "bye!", 5, 0);
     76             pthread_cancel(tid);
     77             
     78             break;
     79         }
     80             
     81         if (g_flag_exit)
     82             break;
     83     }
     84 
     85     printf("
    ");
     86 
     87     //关闭套接字
     88     close(clnt_sock_fd);
     89     close(serv_sock_fd);
     90 
     91     return 0;
     92 }
     93 
     94 
     95 
     96 
     97 /*
     98  *@brief  通过getchar()获取输入的字符串
     99  *@param  buff:存放输入字符串
    100  *@return count:输入的字符数
    101  * */
    102 int getchar_input_str(char * input_buff)
    103 {
    104     char input_char, count = 0;
    105     
    106     /*获取输入字符*/
    107     while((input_char = getchar()) != '
    '){
    108         input_buff[count] = input_char;
    109         count ++;
    110     }
    111     /*清除键盘输入缓存*/
    112     if(input_char != '
    '){
    113         while(((input_char = getchar()) != '
    ') && (input_char != EOF));
    114     }
    115     /*字符串结尾以‘’结束*/
    116     input_buff[count] = '';
    117     
    118     return count;
    119     
    120 }
    serve Code

    演示效果:

  • 相关阅读:
    装饰器
    返回函数
    用Token令牌维护微服务之间的通信安全的实现
    用Windbg来分析.Net程序的dump
    Windows下docker的安装,将ASP.NET Core程序部署在Linux和Docker中
    StackExchange.Redis学习笔记(五) 发布和订阅
    StackExchange.Redis学习笔记(四) 事务控制和Batch批量操作
    StackExchange.Redis学习笔记(三) 数据库及密码配置 GetServer函数
    StackExchange.Redis学习笔记(二) Redis查询 五种数据类型的应用
    Task及Mvc的异步控制器 使用探索
  • 原文地址:https://www.cnblogs.com/lgslearn/p/14776880.html
Copyright © 2011-2022 走看看