首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux c实现一对一通信

在Linux环境下使用C语言实现一对一通信,通常可以采用以下几种常见的方法:

一、基于套接字(Socket)的TCP通信

  1. 基础概念
    • 套接字是一种网络通信的端点抽象,在Linux中,通过socket函数创建套接字。对于一对一通信,TCP协议比较合适,因为它提供可靠的、面向连接的字节流服务。
    • 服务器端通过bind函数将套接字绑定到一个特定的IP地址和端口上,然后使用listen函数监听连接请求。客户端使用connect函数向服务器发起连接请求,服务器使用accept函数接受连接,之后双方就可以通过套接字进行数据传输。
  • 优势
    • 可靠性高,数据按照顺序准确传输,适用于对数据准确性要求较高的场景。
    • 易于理解和实现基本的通信逻辑。
  • 应用场景
    • 网络聊天程序中的一对一聊天功能。
    • 远程命令执行工具,客户端发送命令,服务器端执行并返回结果。
  • 示例代码(服务器端)
代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};

    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址结构
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 绑定套接字到地址
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port %d
", PORT);

    // 接受连接
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 接收数据
    int valread = read(new_socket, buffer, BUFFER_SIZE);
    printf("Received: %s
", buffer);

    // 发送响应
    const char *response = "Hello from server";
    send(new_socket, response, strlen(response), 0);

    close(new_socket);
    close(server_fd);
    return 0;
}

示例代码(客户端)

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char *message = "Hello from client";
    char buffer[BUFFER_SIZE] = {0};

    // 创建套接字
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("
 Socket creation error 
");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // 将IPv4地址从文本转换为二进制形式
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
        printf("
Invalid address/ Address not supported 
");
        return -1;
    }

    // 连接服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("
Connection Failed 
");
        return -1;
    }

    // 发送数据
    send(sock, message, strlen(message), 0);
    printf("Sent: %s
", message);

    // 接收响应
    int valread = read(sock, buffer, BUFFER_SIZE);
    printf("Received: %s
", buffer);

    close(sock);
    return 0;
}

二、基于命名管道(FIFO)的一对一通信

  1. 基础概念
    • 命名管道是一种特殊的文件类型,允许不同进程之间进行通信。在Linux中,可以使用mkfifo函数创建命名管道。
    • 一个进程以读的方式打开命名管道,另一个进程以写的方式打开,就可以实现数据的传输。
  • 优势
    • 实现简单,在同一台机器上的进程间通信效率较高。
    • 不需要复杂的网络设置。
  • 应用场景
    • 同一主机上的本地进程间简单数据交换,例如日志收集进程和被监控进程之间的通信。
  • 示例代码(创建和使用命名管道)
代码语言:txt
复制
// 创建命名管道(在服务器端或先运行的进程)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define FIFO_NAME "my_fifo"

int main() {
    if (mkfifo(FIFO_NAME, 0666) < 0 && errno!= EEXIST) {
        perror("mkfifo");
        return 1;
    }
    return 0;
}
代码语言:txt
复制
// 写入数据到命名管道(客户端)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define FIFO_NAME "my_fifo"

int main() {
    int fd = open(FIFO_NAME, O_WRONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }
    const char *message = "Hello from writer";
    write(fd, message, strlen(message));
    close(fd);
    return 0;
}
代码语言:txt
复制
// 从命名管道读取数据(服务器端)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define FIFO_NAME "my_fifo"

int main() {
    int fd = open(FIFO_NAME, O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }
    char buffer[1024];
    int n = read(fd, buffer, sizeof(buffer));
    printf("Received: %s
", buffer);
    close(fd);
    return 0;
}

三、可能遇到的问题及解决方法

  1. 套接字通信中的连接失败
    • 原因可能是服务器未正确绑定地址或者端口被占用,或者客户端连接的IP地址或端口错误。
    • 解决方法:检查服务器端的bind函数中的地址和端口设置,确保端口未被其他进程占用(可以使用netstat -tlnp命令查看端口使用情况)。对于客户端,检查连接的IP地址是否为服务器的正确地址,端口是否正确。
  • 命名管道通信中的阻塞问题
    • 当以读方式打开命名管道时,如果没有对应的写进程打开,读操作会阻塞;同理,以写方式打开时,如果没有读进程打开,写操作会阻塞。
    • 解决方法:可以根据需求设置非阻塞模式(使用fcntl函数设置O_NONBLOCK标志),但需要注意处理非阻塞模式下可能出现的特殊情况,如没有数据可读或者没有空间可写时的情况。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

linux c++进程间通信_c++多线程通信

1.Linux“线程” 进程与线程之间是有区别的,不过linux内核只提供了轻量进程的支持,未实现线程模型。Linux是一种“多进程单线程”的操作系统。...目前Linux中最流行的线程机制为LinuxThreads,所采用的就是线程-进程“一对一”模型,调度交给核心,而在用户级实现一个包括信号处理在内的线程管理机制。...使用Linuxthread库需要2.0以上版本的Linux内核及相应版本的C库(libc 5.2.18、libc 5.4.12、libc 6)。 2....Linux下的C语言编程有多种线程同步机制,最典型的是条件变量(condition variable)。...下多线程的控制及线程间通信编程方法,给出了一个生产者/消费者的实例,并将Linux的多线程与WIN32、VxWorks多线程进行了类比,总结了一般规律。

3.8K10

图解 | Linux进程通信 - 管道实现

本文主要介绍 管道 的原理与实现。 一、管道的使用 管道 一般用于父子进程之间相互通信,一般的用法如下: 父进程使用 pipe 系统调用创建一个管道。.../pipe parent read 11 bytes data: hello world 二、管道的实现 每个进程的用户空间都是独立的,但内核空间却是共用的。所以,进程间通信必须由内核提供服务。...前面介绍了 管道(pipe) 的使用,接下来将会介绍管道在内核中的实现方式。 本文使用 Linux-2.6.23 内核作为分析对象。 1....管道对象 在 Linux 内核中,管道使用 pipe_inode_info 对象来进行管理。...三、思考一下 管道读写操作的实现已经分析完毕,现在我们来思考一下以下问题。 1. 为什么父子进程可以通过管道来通信?

4.1K52
  • 串口通信Serial Port类C++实现

    本文转载自串口通信Serial Port类C++实现 串口介绍 串口叫做串行接口,也称串行通信接口,按电气标准及协议来分包括RS-232、RS-422、RS485、USB等。...RS-232-C、RS-422与RS-485标准只对接口的电气特性做出规定,不涉及接插件、电缆或协议。USB是近几年发展起来的新型接口标准,主要应用于高速数据传输领域。...RS-422:为改进RS-232通信距离短、速率低的缺点,RS-422定义了一种平衡通信接口,将传输速率提高到10Mb/s,传输距离延长到 4000英尺(速率低于100kb/s时),并允许在一条平衡总线上连接最多...代码实现 CnComm串口通讯库v1.5 文档、范例的下载链接 ....v1.03 - Serial Port Wrapper http://www.codeproject.com/KB/system/cserialport.aspx Serial library for C+

    4.7K50

    C 链表 - linux 如何实现

    链表是基本数据结构, 一开始学习数据结构时, 我一般这么定义, 对应实现从头或尾插入的处理函数, struct int_node_old { int val; struct int_node_old...= NULL; list = list->next); list->next = new; new->next = NULL; } 但是发现, 如果这么定义的话,每次实现一个list的结构...查看linux的源码, 发现linux中也为我们提供了相似的实现(源码), 把一些共性统一起来。 类是 python 中for_each处理,有些意思。...linux 下的链表定义在文件 include/linux/types.h, 采用的是双向列表 struct list_head { struct list_head *next, *prev;...list 利用这个定义, 我定义了一个自己的list数据结构, 并copy了一些接口实现,感受下,linux 是如何管理链表的。

    2.7K30

    【Linux】进程间通信——管道通信

    为什么可以实现通信?...管道通信的原理 首先要实现管道通信肯定不能是进程之间某一个进程提供资源,应该是操作系统提供资源,因为进程之间的资源都是相互独立的,就比如说,之前实验过的,父进程的代码中有一个全局变量,当父子进程不修改只读时...第一步:创建管道 第二步:创建子进程 第三步:根据父子进程的通信的要求删除没有必要的端口 第四步:进行通信 用代码实现管道通信 管道接口: #include #include...总结 管道(Pipe)作为 Linux 进程间通信(IPC)机制之一,提供了一种简单而高效的字节流通信方式,特别适用于父子进程之间的数据传输。...在不同场景下,选择合适的通信方式,才能充分发挥 Linux 进程间通信的优势,提高程序的稳定性和性能。

    5700

    【Linux】进程间通信之管道实现进程池

    一、管道的特点 只能用于具有共同祖先的进程之间进行通信,通常,一个管道由一个进程创建,然后该进程调用fork创建子进程,此后父子进程就可以使用该管道进行通信 管道面向字节流,即管道不晓得自己里面的内容,...所以我们引入池的概念,进程池可以保证在我们需要使用进程的情况下,由于提前创建了子进程,我们直接分配就行了,避免了我们需要大量进程的情况下操作系统很吃力的情况,对提前创建好的这些子进程进行先描述后组织的 2、用管道实现一个简易进程池...,右边为子进程fd,断开父进程fd,然后进程等待 //父进程断开后子进程会在管道中读到0,即文件结束,然后子进程就会终止 //然后被父进程回收 for(const auto &c...: channels){ close(c...._cmdfd); waitpid(c.

    11010

    什么是 IP 隧道,Linux 怎么实现隧道通信?

    IP 隧道 Linux 原生支持多种三层隧道,其底层实现原理都是基于 tun 设备。我们可以通过命令 ip tunnel help 查看 IP 隧道的相关操作。...实践 IPIP 隧道 我们下面以 ipip 作为例子,来实践下 Linux 的隧道通信。本文以前文的 Linux 路由机制作为基础,不清楚 Linux 路由的可以先翻看下那篇文章再来看。...10.10.100.10 dev tun2 当做完上述配置,两个 tun 设备端点就可以互通了,如下: [root@by ~]# ip netns exec ns1 ping 10.10.200.10 -c...以上便是大体的 ipip 隧道通信过程,下面我们可以再抓包进一步验证。...总结 现在的 Linux 内核原生支持 5 种隧道协议,它们底层实现都是采用 tun 虚拟设备。 我们熟知的各种 V** 软件,其底层实现都离不开这 5 种隧道协议。

    7.5K30

    共享内存+互斥量实现 Linux 进程间通信

    一、共享内存简介     共享内存是进程间通信中高效方便的方式之一。...共享内存并未提供进程同步机制,使用共享内存完成进程间通信时,需要借助互斥量或者信号量来完成进程的同步。这里说一下互斥量与信号量的区别。...互斥量用于线程的互斥,信号量用于线程的同步,这是互斥量与信号量的本质区别,其次信号量实现互斥量的功能。    ...四、 示例源码     鄙人以实际项目开发过程中实现进程间通信的源码,为大家展示如何利用上面总结的系统调用接口 来实现进程间的通信。 1.  定义存储成员变量的类,共享内存将用于存放该类的成员数据。.../ALG.out",shmId.c_str(),plain_path.c_str(),plain_offset.c_str(),plain_num.c_str(),plain_len.c_str()};

    2.3K30

    Linux进程通信

    Linux进程通信 1 管道(pipe) 1.1 无名管道 1.1.1 概念和相关知识 1.1.2 相关函数 1.2 命名管道 1.2.1 概念及相关知识 1.2.2 相关函数 2 信号量(semaphore...1.1 无名管道 1.1.1 概念和相关知识 无名管道只能用于具有亲缘关系的进程之间的通信,通常一个管道由一个进程创建,然后实现两个进程间的通信时必须通过fork创建子进程,实现父子进程之间的通信。...在Linux系统中专门设置了一种特殊的系统文件-管道文件——FIFO的文件形式存在于文件系统中,这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就可以通过FIFO进行彼此间的通信...共享内存是最快的IPC方式,往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。...在Linux系统中,1024以下的端口只有拥有root权限的程序才能绑定。

    1.9K20

    【Linux】进程通信之匿名管道通信

    一、进程间进行通信的目的 我们往往需要多个进程协同,共同完成一些事情。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。...操作系统提供的资源不同,就决定了有不同的通信方式。 二、管道通信 2.1、匿名管道通信的原理 基于文件的方式,让不同进程看到同一份资源的通信方式,叫做管道,管道通信只能为单向通信。...前面也说过,管道通信为单向通信,所以如果想让父进程写子进程读,就关闭父进程的读端关闭子进程的写端,反之亦然。...匿名管道只能让具有血缘关系的进程进行进程通信,常用于父子进程之间进行进程通信。...2.3、匿名管道通信的简单实现 #include #include #include #include #include

    17310

    【Linux】详解如何利用共享内存实现进程间通信

    这种方式常常用于加速进程间的通信,因为数据不需要在不同的进程间进行拷贝。 在操作系统中,共享内存通常是通过映射一段能被其他进程所访问的内存实现的。...五、代码实现共享内存通信 5.1、获取key值 其实获取key可以封装成函数也可以不封装,这里我是将其封装成函数了。...原因是:" << strerror(errno) << endl; exit(1); } return key; } 5.2、创建共享内存 共享内存是为了实现两方或是多方通信的...,这里我就设置成为两方通信。...七、说明 因为实现共享内存的文件数较多,所以以上并不是全部代码,如果想获取全部实现代码,请移步到本人码云:C++代码: C++代码保存的地方 - Gitee.com

    1.9K10
    领券