socket编程之read()/write()

6.read()/write()

6.1 包含头文件
#include <unistd.h>
6.2 函数主体
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

参数说明:

  • int fd

​ 该参数指明从文件描述符fd的缓冲区读/写。

  • void *buf

​ read()函数读到的数据将保存到buf所指向的空间中,该参数为void*(无类型指针)表明用户可以传入任何类型的指针,一般我们可以传入char型数组或指针来接收数据,但是如何接收int类型的数据,我目前还没有办法,欢迎大佬指点~

  • size_t count

​ 这参数限制了读取/写入的字节数,即如果读缓冲区有20字节数据,如果调用read()时count设置为10,则只会返回10个字节数据。如果读缓冲区有7字节数据,如果调用read()时count设置为10,则read()函数会正常返回7字节的数据,而不会出现错误。

  • const void *buf

​ 这里加const表明指向常量的指针。

6.3 返回值

成功将返回读取/写入的字节数,返回的数小于请求的字节数,也属于成功返回;size_t 和 ssize_t 分别表示无符号整型数据和有符号整型数据。
错误返回-1,错误类型如下:

错误类型解释
EAGAIN文件描述符 fd 引用套接字以外的文件,并已标记为非阻塞 (O_NONBLOCK),读取/写入将阻塞。
EBADFfd 不是有效的文件描述符或未打开。
EFAULTbuf 位于可访问的地址空间之外。
EINTR在读取数据的第一个字节之前,呼叫被信号中断;
EISDIRfd指向一个目录
6.4 结束

read()和write()用法较为简单,但是针对这两个函数进一步补充说明:

  • read()和write()函数并不是专门为socket编程设计的,socket编程读写操作推荐用send()/recv()函数。而read()和write()适用于所有的文件读写,因为Linux下一切皆文件,所以每个套接字都可以看作一个文件,也可以使用read()和write()函数进行读写操作。
  • socket是全双工的,这就表明通信的双方建立socket连接后,是可以同时进行读写操作的,因为socket的读缓冲区和写缓冲区是独立的两个通道,互补影响。
  • 读写操作时,还需掌握一个概念:文件偏移量,该偏移量指明了目前打开的文件描述符下一次读取/写入数据时的位置。事实上,内核使用3种数据结构来表示打开的文件,这点在之后的文件IO文章种将详细介绍,此处重点谈论socket,故不再赘述。
  • 简单示例代码
#include<iostream>
#include<unistd.h>
#include<string.h>    	 //memset()函数需要头文件
#include<sys/types.h>	 //open()函数包含头文件
#include<sys/stat.h>     //open()函数包含头文件
#include<fcntl.h>

#define handle_error(msg) do {perror(msg); exit(EXIT_FAILURE); } while (0)  

using namespace std;

int main()
{
   const char *ch = "hello! \n";
// int buf[80];
   char *buff = new char[80];
// memset(buf,0,sizeof(buf));
   int fd = -1;
   int ret = -1;
   fd = open("/home/root/test/test.txt",O_RDWR|O_APPEND); //以可读/可写、追加的方式打开文件

   ret = read(fd,buff,5);     //从fd中读取20个字符
   cout<<buff<<endl;

   ret = write(fd,ch,strlen(ch));   //在文档末尾写入字符
   if (ret == -1){
      handle_error("write");
   }
   delete [] buff;           //释放内存
   close(fd);                //关闭文件
   return 0;
}

这个项目算是一个进阶,可以了解一下:代码传送门

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的例子,演示如何使用C语言编写一个简单的socket程序,以发送文件。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> #define PORT 8080 #define MAX_BUFFER_SIZE 1024 int main(int argc, char const *argv[]) { int sockfd, connfd; struct sockaddr_in servaddr, clientaddr; char buffer[MAX_BUFFER_SIZE]; char filename[256]; int n; // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf("Failed to create socket.\n"); exit(EXIT_FAILURE); } // 设置地址信息 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(PORT); // 绑定端口 if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) { printf("Failed to bind socket.\n"); exit(EXIT_FAILURE); } // 监听端口 if (listen(sockfd, 5) != 0) { printf("Failed to listen on socket.\n"); exit(EXIT_FAILURE); } printf("Server listening on port %d.\n", PORT); // 接受连接 connfd = accept(sockfd, (struct sockaddr *)&clientaddr, (socklen_t*)&n); if (connfd < 0) { printf("Failed to accept connection.\n"); exit(EXIT_FAILURE); } printf("Client connected: %s:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port)); // 读取文件名 memset(buffer, 0, MAX_BUFFER_SIZE); read(connfd, buffer, MAX_BUFFER_SIZE); sscanf(buffer, "%s", filename); // 打开文件 int fd = open(filename, O_RDONLY); if (fd < 0) { printf("Failed to open file.\n"); exit(EXIT_FAILURE); } // 发送文件内容 memset(buffer, 0, MAX_BUFFER_SIZE); while ((n = read(fd, buffer, MAX_BUFFER_SIZE)) > 0) { if (write(connfd, buffer, n) < 0) { printf("Failed to send file.\n"); exit(EXIT_FAILURE); } memset(buffer, 0, MAX_BUFFER_SIZE); } printf("File sent successfully.\n"); // 关闭连接和套接字 close(connfd); close(sockfd); return 0; } ``` 该程序的工作流程如下: 1. 创建套接字并绑定端口。 2. 监听端口并等待连接。 3. 接受连接,并读取客户端发送的文件名。 4. 打开文件并读取文件内容。 5. 将文件内容写入套接字,发送给客户端。 6. 关闭连接和套接字。 这是一个非常简单的例子,实际中可能需要添加更多的错误检查和异常处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值