Linux TCP通信例程

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

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

Linux TCP通信例程
 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:

Linux TCP通信例程
#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\r\n");
    }
   
    //读取服务器传回的数据
    char buffer[40];
    read(sock, buffer, sizeof(buffer)-1);
   
    printf("Message form server: %s\n", buffer);
   
   //向serve端发送数据
    char str[] = "Hello!";
    int count = 0, err;
    while ((err = write(sock, str, sizeof(str))) <= 0 && count++ < 10) {
        printf("wait %d\n", err);
        sleep(1);
    }
    
   
    //关闭套接字
    close(sock);

    return 0;
}
client code

 

serve code:

Linux TCP通信例程
#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("监听结束\n");
    //接收客户端请求
    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\n", err);
        sleep(1);
    }
    
    printf("Message form client: %s\n", buffer);
   
    //关闭套接字
    close(clnt_sock);
    close(serv_sock);

    return 0;
}
serve Code

 

运行演示效果:

Linux TCP通信例程

 

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

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

Linux TCP通信例程

 

 

代码如下:

client code:

Linux TCP通信例程
  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\n", 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\r\n");
 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("\033[5D");
 66         printf("Message form serve: %s\r\nself:", read_buff);
 67         fflush(stdout);
 68         if (read_buff[0] == 'b' && read_buff[1] == 'y' && read_buff[2] == 'e') {
 69             printf("exit connect\r\n");
 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("\n");
 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()) != '\n'){
102         input_buff[count] = input_char;
103         count ++;
104     }
105     /*清除键盘输入缓存*/
106     if(input_char != '\n'){
107         while(((input_char = getchar()) != '\n') && (input_char != EOF));
108     }
109     /*字符串结尾以‘\0’结束*/
110     input_buff[count] = '\0';
111     
112     return count;
113     
114 }
client Code

 

serve code:

Linux TCP通信例程
  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\n", 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("监听结束\n");
 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\r\n");
 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("\033[5D");
 71         printf("Message form client: %s\r\nself:", read_buff);
 72         fflush(stdout);
 73         if (read_buff[0] == 'b' && read_buff[1] == 'y' && read_buff[2] == 'e') {
 74             printf("exit connect\r\n");
 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("\n");
 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()) != '\n'){
108         input_buff[count] = input_char;
109         count ++;
110     }
111     /*清除键盘输入缓存*/
112     if(input_char != '\n'){
113         while(((input_char = getchar()) != '\n') && (input_char != EOF));
114     }
115     /*字符串结尾以‘\0’结束*/
116     input_buff[count] = '\0';
117     
118     return count;
119     
120 }
serve Code

 

演示效果:

Linux TCP通信例程

 

上一篇:ciscn_2019_ne_5


下一篇:【14】利用函数的凹凸性证明一道积分不等式