零基础入门Linux网络编程:C 语言网络编程中的数据收发函数解析与示例

在 C 语言网络编程中,数据的收发是至关重要的部分。Linux 提供了一系列系统调用来完成这些操作,包括 readwriterecvfromrecvmsgrecvmmsgsendsendtosendmsgsendfilesendmmsgcmsg 等函数。本文将详细解析这些函数的作用,并提供相应的示例代码。

1. read 和 write

readwrite 是基本的 I/O 操作函数,也可以用于套接字通信。

read 函数:

ssize_t read(int fd, void *buf, size_t count);
  • fd:文件描述符(包括套接字描述符)。
  • buf:存储读取数据的缓冲区。
  • count:要读取的字节数。
  • 返回值:成功返回读取的字节数,失败返回 -1。

示例代码:

char buffer[1024];
ssize_t bytes = read(socket_fd, buffer, sizeof(buffer));
if (bytes > 0) {
    printf("Received: %s\n", buffer);
}

write 函数:

ssize_t write(int fd, const void *buf, size_t count);
  • 用于向文件描述符(套接字)写入数据。
  • 返回值:成功写入的字节数,失败返回 -1。

示例代码:

const char *message = "Hello, Server";
write(socket_fd, message, strlen(message));

2. recv、recvfrom 和 recvmsg

这三个函数用于接收数据,通常用于 UDP 通信。

recv函数:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • sockfd:套接字描述符。
  • buf:存储数据的缓冲区。
  • len:缓冲区大小。
  • flags:可选标志位。
char buffer[1024];
int bytes_received = recv(client_sock, buffer, sizeof(buffer), 0);
if (bytes_received > 0) {
    printf("Received: %s\n", buffer);
}

recvfrom 函数:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
  • sockfd:套接字描述符。
  • buf:存储数据的缓冲区。
  • len:缓冲区大小。
  • flags:可选标志位。
  • src_addr:发送方地址信息。
  • addrlen:地址结构体大小。

示例代码:

struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
char buffer[1024];
ssize_t bytes = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &addr_len);

recvmsg 函数:

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
  • msg 结构体包含多个缓冲区,用于接收更复杂的数据结构。

示例代码:

struct iovec iov[1];
char buffer[1024];
iov[0].iov_base = buffer;
iov[0].iov_len = sizeof(buffer);
struct msghdr msg = {0};
msg.msg_iov = iov;
msg.msg_iovlen = 1;
recvmsg(socket_fd, &msg, 0);

3. recvmmsg(批量接收消息)

recvmmsg 用于一次接收多个消息,提高性能。

int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);

示例代码:

struct mmsghdr msgs[2];
struct iovec iovecs[2];
char buffers[2][1024];
for (int i = 0; i < 2; i++) {
    iovecs[i].iov_base = buffers[i];
    iovecs[i].iov_len = sizeof(buffers[i]);
    msgs[i].msg_hdr.msg_iov = &iovecs[i];
    msgs[i].msg_hdr.msg_iovlen = 1;
}
recvmmsg(socket_fd, msgs, 2, 0, NULL);

4. send、sendto 和 sendmsg

send

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 适用于 TCP 连接,发送数据。

示例代码:

const char *message = "Hello, Client";
send(socket_fd, message, strlen(message), 0);

sendto

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
  • 适用于 UDP,向指定地址发送数据。

示例代码:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr);
sendto(socket_fd, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));

sendmsg

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
  • 发送多部分数据。

示例代码:

struct iovec iov[1];
char buffer[] = "Hello";
iov[0].iov_base = buffer;
iov[0].iov_len = sizeof(buffer);
struct msghdr msg = {0};
msg.msg_iov = iov;
msg.msg_iovlen = 1;
sendmsg(socket_fd, &msg, 0);

5. sendfile(零拷贝传输文件)

sendfile 用于将文件直接发送到套接字,提高性能。

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

示例代码:

int file_fd = open("test.txt", O_RDONLY);
sendfile(socket_fd, file_fd, NULL, 1024);

6. sendmmsg(批量发送消息)

sendmmsg 适用于需要发送多个消息的场景。

int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);

示例代码:

struct mmsghdr msgs[2];
sendmmsg(socket_fd, msgs, 2, 0);

7. cmsg(控制消息)

用于发送或接收附加信息,如文件描述符。

struct cmsghdr *cmsg;

示例代码:

char control[CMSG_SPACE(sizeof(int))];
struct msghdr msg = {0};
msg.msg_control = control;
msg.msg_controllen = sizeof(control);

以上函数是 C 语言网络编程中数据收发的核心部分,掌握它们有助于编写高效的网络程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

银河码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值