Unix网络编程 第四章 笔记

Unix网络编程 第四章 笔记

基本TCP套接字编程


1. 概述

    服务器首先启动,稍后某个时刻客户启动,它试图连接到服务器。假设客户给服务器发送一个请求,服务器处理该请求,并给客户发回一个响应。这个过程一直持续下去,直到客户关闭连接的客户端,从而给服务器发送一个EOF(文件结束)通知为止。服务器接着也关闭连接的服务器端,然后结束运行或者等待新的客户连接。


2. socket函数

family参数指定协议族,也被称为协议域。type参数指定套接字类型。protocol参数是某个协议类型常值,或者设为0,以选择给定family和type组合的系统默认值。
#include 
    
    
     
     
int socket(int family, int type, int protocol);

//返回:若成功则返回非负描述符,出错则为-1
//family是协议族,type表明套接字类型
    
    


3. connect函数

#include 
    
    
     
     

int connect( int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
//若成功返回0,否则返回-1
//sockfd是由socket函数获得的套接字描述符,第二、第三个参数分别是一个指向套接字地址结构的指针和该机构的大小
    
    
调用connect函数前不一定调用bind函数,因为如果有需要,内核会确定源IP地址,并选择一个临时端口作为源端口。
如果是TCP套接字:
(1)若TCP客户没有收到SYN分节的响应,内核发送一个SYN,若无响应则6s后再发送一个,若仍无反应,则等待24s后再发送一个。若总共75s没有收到响应则返回ETIMEDOUT错误。
(2)若对客户的SYN的相应是RST(复位),表明在指定的端口上没有进程在等待与之连接(例如服务器进程没有在运行)。这是一种硬错误,客户一接收到RST就马上返回ECONNREFUSES错误。
产生RST的三个条件:
目的地为某端口的SYN到达,然而该端口上没有正在监听的服务器;TCP想取消一个已有连接;TCP接收到一个根本不存在的连接上的分节。
(3)若客户发送的SYN在中间某个路由器上引起了一个"destination unreachable"(目的地不可达)ICMP错误,认为是一种软错误。然后按照第一种情况的时间间隔发送SYN。
若connect失败则该套接字不再可用,必须关闭。需要重新调用socket函数获取新的套接字

4. bind函数

5. listen函数

当socket函数创建一个套接字时,它被假设为一个主动套接字(一个将调用connect发起连接的客户套接字),listen函数将一个未连接的套接字转换成一个被动套接字,指示内核应接受指向该套接字的连接请求。调用listen导致套接字从CLOSED状态转向Listen状态。

#include 
      
      
       
       

int listen(int sockfd, int backlog);
//成功:返回0,出错则返回-1
      
      
函数的参数backlog规定了内核应该为相应套接字排队的最大连接个数。

未完成连接队列:
由某个客户端发出并到达服务器,而服务器正在等待完成相应的TCP三路握手过程,这些套接字处于SYN_RCD状态
已完成连接队列:
每个已完成三次握手过程的客户对应其中一项。这些套接字处于ESTABLISHED状态。
未完成连接队列的个数+已完成连接队列的个数不超过backlog



6. accept函数

由TCP服务器调用,用于从已完成连接队列队头返回下一个已完成连接,如果已完成连接为空,则进程被投入睡眠。

7. fork函数以及exec函数

fork调用一次,在父进程中返回一次,得到子进程的进程ID号,在子进程返回一次,返回0.
父进程在fork之前打开的所以描述符在fork返回后由子进程分享。
如果父进程在fork后得到一个自身的副本,可以调用exec函数将当前进程映像替换成新的程序文件。称调用exec的进程为调用进程,新执行的程序为新程序。
exec函数只有在出错时才返回到调用者,否则,控制就被传递给新程序的起始点,通常是main函数。

8.并发服务器

每个文件或者套接字会有一个引用计数器。当父进程fork产生子进程的时候,套接字会被复制,相应的引用计数器也会增加。而对套接字的清理要在套接字的引用计数器清零时才会执行,所以需要子进程以及父进程都关闭套接字。

9.close函数

调用close函数可以减少套接字的引用计数。

10. getsockname和getpeername函数

getsockname返回与某个套接字关联的本地协议地址,getpeername返回与某个套接字关联外地协议地址。
在一个没有调用bind的TCP客户上,connect成功返回后,getsockname用于返回由内核赋予该连接的本地IP地址和本地IP端口号
以端口号0调用bind(告知内核去选择本地端口号)后,getsockname用于返回由内核赋予的本地端口号。
getsockname可以用于获取某个套接字的地址族
在一个以通配地址调用bind的TCP服务器上,与某个客户一旦建立(accept成功返回),getsockname就可以用于返回由内核赋予该连接的本地IP地址。在这样的调用中,套接字描述符参数必须是已连接套接字的描述符,而不是监听套接字的描述符。

当一个服务器是由调用过accept的某个进程通过调用exec执行程序时,它能够获取客户身份的唯一途径就是调用getpeername

11. 小结

所有客户和服务器都是从调用socket开始,它返回一个套接字描述符。客户随后调用connect,服务器则调用bind,listen,accept。套接字通常使用标准的close函数关闭,在6.6节可以看到使用shutdown函数关闭套接字的另一种方法。7.5节还要看到SO_LINGER套接字选项对关闭套接字的影响。

大多数TCP服务器都是并发的,他们为每个待处理的客户连接调用fork派生一个子进程
后续将会看到,大多数UDP服务器都是迭代的。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值