1、文件描述符
在学习高级I/O函数时,我们需要对linux的文件描述符,文件描述符表等等有一定了解,在linux系统中,一切皆文件,
每一个进程都在PCB维护一个文件描述符表,文件描述符是指向一个进程打开的文件,在文件描述符表中,0、1、2三个文件描述符分别被标准输入(STDIN)、标准输出(STDOUT)、标准错误输出(STDERR)占用,所以我们自己使用的文件描述符都是从3号开始的(会自动寻找到最小的还没用的,或是已经关闭的文件描述符使用)
文件描述符是一个整数值
文件描述符详细—传送门
2、dup和dup2函数
用于复制文件描述符,将某个文件描述符(比如标准输出)重定向到一个文件,又或者是一个网络连接(套接字)。
dup函数创建一个新的文件描述符,返回新的文件描述符,创建的新的文件描述符和原有的文件描述符(也就是传入的参数fd,指向相同的文件、管道或是网络连接),同时要注意的是,dup返回的文件描述符总是取系统当前可用的最小整数值。
dup2和dup函数类似,只不过返回的文件描述符的值要小于给的第二个参数。
两个函数调用失败都返回-1,设置errno
#include <unistd.h>
int dup(int fd)
int dup2(int fd_one , int fd_two)
3、代码示例
我希望弄这么一个程序,服务器和客户端之间进行数据传输,本来应该是通过套接字进行数据传输,我在服务器端将accept到的客户端套接字socket指向标准输出,那么在服务器打印(printf)的数据应该就会传送到客户端,客户端在读取出来显示到标准输出
server:
1 #include <sys/socket.h>
2 #include <netinet/in.h>
3 #include <arpa/inet.h>
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <string.h>
9
10 #define PORT 10086
//若main函数没有参数,这里记得给void,反正我的虚拟机这个位置不报错但是程序执行就会有问题
11 int main(void)
12 {
13 int lfd , cfd;
14 struct sockaddr_in address;
15 bzero( &address , sizeof(address) );
16 address.sin_family = AF_INET;
17 address.sin_addr.s_addr = htonl(INADDR_ANY);
18 address.sin_port = htons(PORT);
19
20 lfd = socket(AF_INET, SOCK_STREAM, 0);
21 if (lfd < 0) {
22 printf("socket() error\n");
23 return -1;
24 }
25 if (bind(lfd, (struct sockaddr*)&address, sizeof(address)) < 0) {
26 printf("bind() error\n");
27 return -1;
28 }
29 listen(lfd, 5);
30 printf("server is ready for client\n");
31
32 struct sockaddr_in addr_client;
33 bzero(&addr_client, sizeof(addr_client));
34 socklen_t client_len = sizeof(addr_client);
35
36 cfd = accept(lfd, (struct sockaddr*)&addr_client, &client_len);
37 if (cfd < 0) {
38 printf("accept() error\n");
39
40 }
41 printf("client is connect....")
42 else
43 {
44 close(STDOUT_FILENO);
45 dup(cfd); //自动赋值到上面close掉的文件描述符的位置,因为是从小开始找到第一个可用的文件描述符
46 printf("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
47 close(cfd);
48 }
49 close(lfd);
50 return 0;
51
52 }
client:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <string.h>
4 #include <sys/socket.h>
5 #include <arpa/inet.h>
6
7
8 #define SERV_IP "127.0.0.1"
9 #define SERV_PORT 10086
10
11 int main(void)
12 {
13 int sfd, len;
14 char buf[BUFSIZ];
15 struct sockaddr_in serv_addr;
16 sfd = socket(AF_INET, SOCK_STREAM, 0);
17
18 bzero(&serv_addr, sizeof(serv_addr));
19 serv_addr.sin_family = AF_INET;
20
21 inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
22
23 serv_addr.sin_port = htons(SERV_PORT);
24
25
26 connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
27 len = read(sfd,buf,sizeof(buf));
28 write(STDOUT_FILENO , buf , len);
29 while(1);
30 }
4、测试
当客户端连接上后,就会将hhhhhhhhhhh…显示在屏幕上了