Linux TCP通信例程

Posted L_G_S

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\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:

#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

 

运行演示效果:

 

例程二: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\\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:

  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通信例程的主要内容,如果未能解决你的问题,请参考以下文章

Python 之 Socket编程(TCP/UDP)

c++ 网络编程TCP/IP linux 下多进程socket通信 多个客户端与单个服务端交互代码实现回声服务器

如何实现LabVIEW和单片机的wifi通信

freecplus框架-tcp网络通信

[Linux 高并发服务器]TCP通信流程

GO语言网络编程