linux网络编程之socket(二):C/S程序的一般流程和基本socket函数

一、基于TCP协议的网络程序

下图是基于TCP协议的客户端/服务器程序的一般流程:

服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。

数据传输的过程:

建立连接后,TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()返回后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。

如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数据。

在学习socket API时要注意应用程序和TCP协议层是如何交互的: 

*应用程序调用某个socket函数时TCP协议层完成什么动作,比如调用connect()会发出SYN段

 *应用程序如何知道TCP协议层的状态变化,比如从某个阻塞的socket函数返回就表明TCP协议收到了某些段,再比如read()返回0就表明收到了FIN段

补充一下,其实TCP 共有11种状态,上图没有出现的CLOSING 状态,当双方同时关闭连接时会出现此状态,替换掉FIN_WAIT2状态。

二、基本socket函数

1、socket函数

包含头文件<sys/socket.h> 功能:创建一个套接字用于通信 原型:int socket(int domain, int type, int protocol); 参数 domain :指定通信协议族(protocol family),AF_INET、AF_INET6、AF_UNIX等 type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW protocol :协议类型,IPPROTO_TCP等;一般由前两个参数就决定了协议类型,设置为0即可。 返回值:成功返回非负整数, 它与文件描述符类似,我们把它称为套接口描述字,简称套接字。失败返回-1

2、bind函数

包含头文件<sys/socket.h> 功能:绑定一个本地地址到套接字 原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数 sockfd:socket函数返回的套接字 addr:要绑定的地址 addrlen:地址长度 返回值:成功返回0,失败返回-1

3、listen函数

包含头文件<sys/socket.h> 功能:将套接字用于监听进入的连接 原型:int listen(int sockfd, int backlog); 参数 sockfd:socket函数返回的套接字 backlog:已完成三次握手的最大连接个数 返回值:成功返回0,失败返回-1

一般来说,listen函数应该在调用socket和bind函数之后,调用函数accept之前调用。 对于给定的监听套接口,内核要维护两个队列: 1、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程 2、已完成连接的队列

如下图所示:

Be careful to differentiate between TCP accepting a connection and placing it on this queue, and the application taking the accepted connection off this queue.

Keep in mind that this backlog value specifies only the maximum number of queued connections for one listening end point, all of which have already been accepted by TCP and are waiting to be accepted by the application. This backlog has no effect whatsoever on the maximum number of established connections allowed by the system, or on the number of clients that a concurrent server can handle concurrently.

If there is not room on the queue for the new connection, TCP just ignores the received SYN. Nothing is sent back (i.e., no RST segment). If the listening server doesn't get around to accepting some of the already accepted connections that have filled its queue to the limit, the client's active open will eventually time out.

In the attempted connection to a nonexistent host,  how frequently the client’s TCP sends a SYN to try to establish the connection. The second segment is sent 3s after the first, the third is sent 6s after the second, the fourth is sent 12s after the third, and soon. This behavior is called exponential backoff.

4、accept函数

包含头文件<sys/socket.h> 功能:从已完成连接队列返回第一个连接,如果已完成连接队列为空,则阻塞。 原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 参数 sockfd:服务器套接字 addr:将返回对等方的套接字地址 addrlen:返回对等方的套接字地址长度 返回值:成功返回非负整数,失败返回-1

5、connect函数

包含头文件<sys/socket.h> 功能:建立一个连接至addr所指定的套接字 原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数 sockfd:未连接套接字 addr:要连接的套接字地址 addrlen:第二个参数addr长度 返回值:成功返回0,失败返回-1

参考:

《Linux C 编程一站式学习》

《TCP/IP详解 卷一》

《UNP》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小二的折腾日记

服务器-Nginx的事件驱动模型

事件驱动概念:在持续的事物管理过程中,由当前时间节点上出现的事件引起的调用可用资源执行相关任务,解决问题,防止事物堆积的一种策略。 一般由:事件收集器、事件发送...

704
来自专栏Laoqi's Linux运维专列

利用iptables防止syn flood攻击

1564
来自专栏Spark学习技巧

Kafka源码系列之源码分析zookeeper在kafka的作用

浪尖的kafka源码系列以kafka0.8.2.2源码为例给大家进行讲解的。纯属个人爱好,希望大家对不足之处批评指正。 一,zookeeper在分布式集群的作...

28410
来自专栏刘望舒

Android网络编程(八)源码解析OkHttp中篇[复用连接池]

1.引子 在了解OkHttp的复用连接池之前,我们首先要了解几个概念。 TCP三次握手 通常我们进行HTTP连接网络的时候我们会进行TCP的三次握手,然后传输数...

25810
来自专栏CSDN技术头条

基于Zookeeper的分布式锁

实现分布式锁目前有三种流行方案,分别为基于数据库、Redis、Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开。我们来看下使用Zo...

2228
来自专栏牛肉圆粉不加葱

Spark executor 模块② - AppClient 向 Master 注册 Application

前一篇文章简要介绍了 Spark 执行模块中几个主要的类以及 AppClient 是如何被创建的,这篇文章将详细的介绍 AppClient 向 Master 注...

612
来自专栏猿人谷

进程控制实验--fork()

进程的控制 实验目的 1、掌握进程另外的创建方法 2、熟悉进程的睡眠、同步、撤消等进程控制方法 实验内容 1、用fork( )创建一个进程,再调用exec( )...

1808
来自专栏猿人谷

TCP第三次握手失败怎么办

笔试题中经常会遇到这个问题:如果tcp建立连接时第三次握手失败,tcp会做何操作?该问题的本质是判断我们对tcp的状态转换是否能有比较深刻的理解。只要理解了下面...

1877
来自专栏决胜机器学习

数据库专题(五) ——Memcached技术

数据库专题(五)——Memcached技术 (原创内容,转载请注明来源,谢谢) 一、Slab分配算法保存数据 Memcached默认只能用1M...

2545
来自专栏Linyb极客之路

RPC框架设计和调用详解

RPC是远程调用过程的简写,是一个协议,处于网络通信协议的第五层:会话层,其下就是TCP/IP协议,在建立在其基础上的通信会话协议。RPC定义了交互的模式,而...

862

扫码关注云+社区