Linux中的read/write和recv/send的区别,并使用recv/send实现简单的聊天功能
Linux中的read/write和recv/send的区别
- read/writeread/writeread/write的用法
- recv/sendrecv/sendrecv/send的用法
- LinuxLinuxLinux中的read/writeread/writeread/write和recv/sendrecv/sendrecv/send的区别
- 下面是一个使用read/write进行文件读写操作的例子:
- 下面是一个使用recv/send进行网络通信的例子:
read/writeread/writeread/write的用法
在 Linux 中,read() 和 write() 是用于在文件描述符上进行数据读写的函数。它们的用法如下:
#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, const void *buf, size_t count);
其中,fdfdfd 是一个已经打开的文件描述符;
bufbufbuf 是一个指向读或写数据的缓冲区指针;
countcountcount 是缓冲区的长度。
read()read()read() 函数用于从文件描述符中读取数据,它会阻塞程序直到读取到数据或发生错误。它返回读取到的字节数,如果返回值为 000,则表示已经到达文件末尾。如果返回值为 −1-1−1,则表示出现了错误,可以通过 errnoerrnoerrno 变量来获取错误码。
write()write()write() 函数用于向文件描述符中写入数据,它会阻塞程序直到所有数据都被写入完毕或发生错误。它返回写入的字节数,如果返回值小于指定的长度,则表示出现了错误。可以通过 errnoerrnoerrno 变量来获取错误码。
需要注意的是,read()read()read() 和 write()write()write() 是基于字节流的,它们不会保留消息的边界信息。如果需要保留消息的边界信息,可以使用 read()read()read() 和 write()write()write() 函数。
recv/sendrecv/sendrecv/send的用法
在 LinuxLinuxLinux 中,recv()和send()recv() 和 send()recv()和send() 是用于在网络套接字上进行数据收发的函数。它们的用法如下:
#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t send(int sockfd, const void *buf, size_t len, int flags);
其中,sockfdsockfdsockfd 是一个已经创建好的、打开的套接字文件描述符;
bufbufbuf 是一个指向接收或发送数据的缓冲区指针;
lenlenlen 是缓冲区的长度;
flagsflagsflags 是一组标志参数,它们控制着函数的行为。
recv()recv()recv() 函数用于从套接字中接收数据,它会阻塞程序直到接收到数据或发生错误。它返回接收到的字节数,如果返回值为 000,则表示连接已经关闭。如果返回值为 −1-1−1,则表示出现了错误,可以通过 errnoerrnoerrno 变量来获取错误码。recv()recv()recv() 函数的常用标志参数有:
- MSG_WAITALL:阻塞等待直到接收到指定长度的数据。
- MSG_PEEK:接收数据但不从接收缓冲区中删除数据。
- MSG_OOB:接收带外数据。
send()send()send() 函数用于向套接字中发送数据,它会阻塞程序直到所有数据都被发送完毕或发生错误。它返回发送的字节数,如果返回值小于指定的长度,则表示出现了错误。可以通过 errnoerrnoerrno 变量来获取错误码。send()send()send() 函数的常用标志参数有:
- MSG_DONTWAIT:非阻塞发送数据。
- MSG_MORE:告诉内核还有更多数据需要发送。
- MSG_NOSIGNAL:在发送数据时忽略 SIGPIPE 信号。
LinuxLinuxLinux中的read/writeread/writeread/write和recv/sendrecv/sendrecv/send的区别
在LinuxLinuxLinux中,read/writeread/writeread/write和recv/sendrecv/sendrecv/send是用于从文件描述符文件描述符文件描述符或套接字套接字套接字进行数据读写的系统调用。它们之间的主要区别如下:
-
参数不同
read/writeread/writeread/write的参数是文件描述符、缓冲区和读/写字节数文件描述符、缓冲区和读/写字节数文件描述符、缓冲区和读/写字节数,
而recv/sendrecv/sendrecv/send的参数是套接字、缓冲区和读/写字节数套接字、缓冲区和读/写字节数套接字、缓冲区和读/写字节数。 -
返回值不同
read/writeread/writeread/write的返回值为已读/写字节数,如果遇到错误则返回-1。
recv/sendrecv/sendrecv/send的返回值为已接收/发送字节数,如果遇到错误则返回-1。 -
应用场景不同
read/writeread/writeread/write通常用于读写普通的文件、管道等读写普通的文件、管道等读写普通的文件、管道等,
而recv/sendrecv/sendrecv/send则用于网络编程中的套接字通信网络编程中的套接字通信网络编程中的套接字通信。 -
处理方式不同
read/writeread/writeread/write在读写时使用文件偏移量来确定从哪里读取或写入数据,并根据需要更新该偏移量。
recv/sendrecv/sendrecv/send则没有类似的偏移量概念,它们一次性读取或发送指定数量的数据。
总体而言,read/writeread/writeread/write适合用于本地文件和管道等,而recv/sendrecv/sendrecv/send适合用于网络通信中的套接字。
下面是一个使用read/write进行文件读写操作的例子:
该程序打开一个名为test.txttest.txttest.txt的文件,并使用readreadread将其内容读取到缓冲区中,然后使用writewritewrite将内容写入标准输出。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>int main() {int fd = open("test.txt", O_RDWR);if (fd == -1) {printf("Failed to open file\\n");exit(1);}char buffer[1024];int num_read = read(fd, buffer, sizeof(buffer));if (num_read == -1) {printf("Failed to read file\\n");exit(1);}int num_written = write(STDOUT_FILENO, buffer, num_read);if (num_written == -1) {printf("Failed to write file\\n");exit(1);}close(fd);return 0;
}
下面是一个使用recv/send进行网络通信的例子:
下面是一个使用recv/send进行网络通信的服务器与客户端互发消息的例子:
// Server
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8081int main()
{int server_sock = socket(AF_INET, SOCK_STREAM, 0);if (server_sock == -1){printf("Failed to create socket\\n");exit(1);}struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);server_addr.sin_addr.s_addr = INADDR_ANY;if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){printf("Failed to bind\\n");exit(1);}if (listen(server_sock, 5) == -1){printf("Failed to listen\\n");exit(1);}printf("Server is listening on port %d...\\n", PORT);struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len);if (client_sock == -1){printf("Failed to accept connection\\n");exit(1);}char buffer[1024];while (1){memset(buffer, 0, sizeof buffer); // 收之前先把缓存区清空int num_received = recv(client_sock, buffer, sizeof(buffer), 0); /收///if (num_received == -1){printf("Failed to receive message\\n");exit(1);}else if (num_received == 0){break; // Client closed connection}printf("Received message: %s", buffer);const char *message = "Hello, client!\\n";int num_sent = send(client_sock, message, strlen(message), 0); ///发if (num_sent == -1){printf("Failed to send message\\n");exit(1);}}close(client_sock);close(server_sock);return 0;
}
该程序创建了一个服务器套接字,绑定到指定端口,并使用listen开始监听。当客户端连接时,使用accept接受连接并进行通信。在接受到客户端发送的消息后,服务器会将其打印出来,并向客户端发送一条回复。
// Client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8081int main()
{int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1){printf("Failed to create socket\\n");exit(1);}struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){printf("Failed to connect\\n");exit(1);}char buffer[1024];while (1){printf("Enter message: ");fgets(buffer, sizeof(buffer), stdin);int num_sent = send(sock, buffer, strlen(buffer), 0); /发/if (num_sent == -1){printf("Failed to send message\\n");exit(1);}else if (num_sent == 0){break; // Server closed connection}memset(buffer, 0, sizeof buffer); // 收之前先把缓存区清空int num_received = recv(sock, buffer, sizeof(buffer), 0); /收//if (num_received == -1){printf("Failed to receive message\\n");exit(1);}else if (num_received == 0){break; // Server closed connection}printf("Received message: %s", buffer);}close(sock);return 0;
}
该程序创建了一个客户端套接字,连接到服务器。在输入一条消息后,使用send向服务器发送该消息,并收到服务器的回复。当检测到服务器关闭连接时,程序退出。
这两个程序可以相互通信,实现简单的聊天功能。