首页
学习
活动
专区
工具
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标志),但需要注意处理非阻塞模式下可能出现的特殊情况,如没有数据可读或者没有空间可写时的情况。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券