1、TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下:
(1)TCP服务端编程的一般步骤为:
- 调用socket函数,创建一个套接字描述符。
- 创建网络地址结构,指定要监听的IP和端口号。
- 调用bind函数,将套接字描述符与网络地址结构绑定。
- 调用listen函数,将套接字描述符转为监听套接字,表示该描述符是用于从指定地址和端口接收连接的。
- 调用accept函数来获取链接。
- 得到连接后使用read和write函数完描述符里读写数据。
- 完成后调用close关闭描述符。
(2)TCP客户端端编程的一般步骤为:
- 调用socket函数,创建一个套接字描述符。
- 创建网络地址结构,指定要连接的服务端的IP和端口号。
- 调用connect函数连接服务端。
- 连接成功后调用read、write函数读写数据
- 完成后调用close关闭描述符。
注:
(1)套接字
TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口。
套接字用(IP地址:端口号)表示。
它是网络通信过程中端点的抽象表示,包含进行网络通信必需的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
(2)套接口
通讯的基石是套接口,一个套接口是通讯的一端。在这一端上你可以找到与其对应的一个名字。一个正在被使用的套接口都有它的类型和与其相关的进程。套接口存在于通讯域中。通讯域是通过套接口通讯来处理一般的线程而引进的一种抽象概念。
(3)错误处理:包裹函数
包裹函数调用实际函数,检查返回值,发生错误终止进程。确定包裹函数名的约定是大写实际函数名的第一个字符。
(4)三次握手
a、对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三次握手,而这个连接的过程是由内核完成,不是这个函数完成的,这个函数的作用仅仅是通知 Linux 内核,让 Linux 内核自动完成 TCP 三次握手连接,最后把连接的结果返回给这个函数的返回值(成功连接为0, 失败为-1)。
通常的情况,客户端的 connect() 函数默认会一直阻塞,直到三次握手成功或超时失败才返回(正常的情况,这个过程很快完成)。
b、listen() 函数的主要作用就是将套接字( sockfd )变成被动的连接监听套接字(被动等待客户端的连接),至于参数 backlog 的作用是设置内核中连接队列的长度,TCP 三次握手也不是由这个函数完成,listen()的作用仅仅告诉内核一些信息。
这里需要注意的是,listen()函数不会阻塞,它主要做的事情为,将该套接字和套接字对应的连接队列长度告诉 Linux 内核,然后,listen()函数就结束。
这样的话,当有一个客户端主动连接(connect()),Linux 内核就自动完成TCP 三次握手,将建立好的链接自动存储到队列中,如此重复。所以,只要 TCP 服务器调用了 listen(),客户端就可以通过 connect() 和服务器建立连接,而这个连接的过程是由内核完成。
c、accept()函数功能是,从处于 established (建立)状态的连接队列头部取出一个已经完成的连接,如果这个队列没有已经完成的连接,accept()函数就会阻塞,直到取出队列中已完成的用户连接为止。
2、UDP通信模型