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 条评论
登录 后参与评论

相关文章

来自专栏老安的博客

openstack neutron-修改新创建安全组的默认规则

1232
来自专栏wym

面向连接的c语言/socket 程序流程(TCP)

   int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData);

922
来自专栏安富莱嵌入式技术分享

【RL-TCPnet网络教程】第19章 RL-TCPnet之BSD Socket服务器

本章节为大家讲解RL-TCPnet的BSD Socket,学习本章节前,务必要优先学习第18章的Socket基础知识。有了这些基础知识之后,再搞本章节会有事半功...

702
来自专栏蓝天

tcpdump命令格式

tcpdump采用命令行方式,它的命令格式为:   tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ]      ...

732
来自专栏蓝天

Tcpdump 的用法

更新时间:2005-12-26 11:55 阅读提示:第一种是关于类型的关键字,主要包括host,net,port, 例如 host 210.27.48.2,指...

974
来自专栏开发与安全

linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数

一、UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX...

2710
来自专栏Jackie技术随笔

htons&ntohs

而TCP/IP协议栈使用大端字节序。应用程序交换格式化数据时,字节序问题就会出现。对于TCP/IP,地址用网络字节序来表示,所以应用程序有时需要在处理器的字节序...

2145
来自专栏用户2442861的专栏

Python 一个简单的python socket编程

http://blog.csdn.net/winnie8829/article/details/37874355

562
来自专栏自动化测试实战

RF接口测试(4)

3447
来自专栏安富莱嵌入式技术分享

【RL-TCPnet网络教程】第20章 RL-TCPnet之BSD Socket客户端

本章节为大家讲解RL-TCPnet的BSD Socket,学习本章节前,务必要优先学习第18章的Socket基础知识。有了这些基础知识之后,再搞本章节会有事半功...

842

扫码关注云+社区