Understanding Unix/Linux Programming 笔记:chapter 11:连接到近端或远端的进程:服务器与Socket(套接字)

本文详细解析了socket编程的基本概念,包括客户/服务模型、主机名和端口、地址族、协议等,并通过bc/dc计算器和远程ls实例展示了如何使用socket实现数据传输。同时,阐述了服务器和客户端程序的流程,以及fdopen与write的区别,最后以远程ls为例说明了服务器与客户端之间的数据交互方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Key-word: fdopen,dopen, socket, bind, listen, accept, connect

基本概念:

       需要由其他人完成的工作称为服务,而自己则是服务的客户。

       fdopen与fopen类似,返回一个FILE*类型的值,不同的是此函数以文件描述符而非文件作为参数。

       fopen打开一个指向文件的带缓冲的连接;popen打开一个指向进程的带缓冲的连接。

       服务器是提供服务的程序,而不是一台计算机。

       Socket编程所涉及到的4个重要概念:

1)客户和服务器

        服务器是提供服务的程序。在Unix中,服务器不是一台计算机。服务器进程等待请求,处理请求,然后循环回去等待下一个请求。客户端进程则不需要循环,它只需建立一个连接,与服务器交换数据,然后继续自己的工作。

2)主机名和端口

        运行于因特网上的服务器其实是某台计算机上运行的一个进程。这台计算机被称为主机。机器通常被指定为一个名字如:www.google.com,被称为主机的名字。服务器在该主机上拥有一个端口。主机和端口的组合才标识了一个服务器。

3)地址族

4)协议

       协议是服务器和客户之间交互的规则。

内容概述:

1、bc/dc计算器

        为了讲解客户/服务模型,介绍了bc/dc计算器程序。该程序主要是通过之前章节讲过的系统调用:pipe, fork, dup, exec 实现的。

      

       bc是客户端,dc是服务端。

       bc与终端之间的连接a和b是默认就存在的,因为bc仍要向终端输入/输出数据,所以就保留下来。bc只需添加与新建的两个pipe之间的连接。

       dc与终端之间也有默认的连接,但是dc不与终端之间进行数据交互,因此就需要关闭与终端的连接,并建立与两个pipe之间的连接,这就用到了dup2指令。

       数据流向是:a, pipe1, pipe2, b。

2、popen:让进程看似文件

       用fdopen, pipe, fork, dup, exec 实现。要实现如下模型,方法与上例类似。

       要向打开的进程写数据时,数据流向是:a, c。

       要从打开的进程读数据时,数据流向是:d, b。

      

3、socket

       管道在一个进程中被创建,通过fork实现共享,因此管道只能连接同一台计算机上的两个进程;而socket可以连接不同主机上的进程。

      

4、服务器程序流程

1)向内核申请一个socket;

       用socket()实现,得到一个sockid;

1)绑定地址到socket,地址包括主机、端口;

       用bind()实现,将1)中的得到的sockid和服务器绑定在一起;

2)在socket上,允许接入呼叫并设置队列长度为1;

       用listen()实现;

4)等待/接收呼叫;

       用accept()实现,accept会阻塞当前进程,直到指定socket上的连接被建立起来,然后accept将返回文件描述符;

       accept()的输入参数中有sockid,但accept()返回的是文件描述符sock_fd,两个都是int型的。

 

5)传输数据;

       fdopen打开4)中得到的文件描述符sock_fd,得到一个FILE *类型的指针;然后用fprintf操作该指针进行输入\出;

6)关闭连接;

       用fclose关闭5)中打开的文件描述符。

 

5、客户端程序流程

1)向内核申请将建立socket;

        用socket()实现,得打一个sock_id;

2)与服务器相连;

        调用connect()实现,此时1)中得到的sockid是一个合法的文件描述符,可以用来进行读写操作;

3)传送数据;

        直接用read和write来读写。

4)挂断;

 

        注意:服务器程序和客户端程序的区别。同样是在获取sock_id之后,服务器端需要先用fdopen打开sock_id,返回一个文件描述符sock_fd,然后再用fprintf对获取的文件描述符操作;而客户端在获取sock_id之后,直接用write, read操作。

       实际是服务器端程序也可以直接用write(sock_fd)来输出数据,只是用fdopen可以将文件描述符定向到缓存的数据流,以便于调用fprintf来进行输出。

       下面给出用fprintf和write输出数据的区别:

write is asystem call: it sends the given characters directly to the operating system,which (in theory, and often in practice) sends them immediately to the outputdevice such as the screen or disk.

fprintf (and fwrite andanything that takes a FILE * argument)is a library call, which buffers, or collects, the data inside your programbefore sending it. This allows it to send larger, more uniform chunks of data,which improves efficiency.

       也就是,服务端程序在调用accept时得到的才是可以进行输入/输出的文件描述符,而客户端程序在connect之后得到的就是合法的文件描述符。fdopen可以将文件描述符转换成缓冲流。

 

6、另一种服务器:远程的ls

       与时间服务器的区别:1)时间服务器的客户端只有发送数据,而远程的ls既有发送又有接受数据;2)远程的ls添加了客户端和服务端之间的协议,用换行符’\n’作为一次数据传送结束的标识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值