套接字编程3(tcp)

tcp通信程序的编写:

套接字编程3(tcp)_第1张图片
第一步在内核里创建了一个套接字socket结构体, 第二步绑定地址信息, 我们相当于有了源端IP(sip)和源端端口(sport), 下一步就是监听, 监听就是将tcp的状态置为listen状态, listen状态的套接字才会处理客户端的连接请求. 这一步完成之后, 我们的网卡是不断从网络上接收数据的. 这时候如果有一个客户端, 客户端给主机发送了一个tcp链接建立请求(syn), 不管是什么请求, 它都是一条数据, 作为一条数据那么就有源端地址信息和对端地址, 有了对端地址信息最终就会到网卡上.
  假设我的监听地址信息是192.168.2.2:8000, 对端端口的地址信息是192.168.2.3:9000用的协议是tcp协议. 源端地址+源端端口+对端地址+对端端口+协议是一个五元组, 五元组就标识了一个通信.
  这条数据经过网卡发送就到达了这边主机, 操作系统收到这条数据之后, 通过目标地址和端口来确定是这个socket的数据, 这个数据就会被放到socket的接收缓冲区里, socket就会发现这个数据是一个连接请求, 就会处理这个连接请求.
  处理这个请求, 就会为我们的这个客户端又单独创建了一个套接字, 将上边的套接字复制了一份出来, 新建的这个socket不仅有源端的地址和端口, 还包含了对端的地址和端口(dip+dport)
  原来的套接字只用于接收新的连接请求, 新建的套接字是专门用来跟指定的客户端来进行通信的
套接字编程3(tcp)_第2张图片
客户端如果在服务端进入监听状态之前发送连接请求, 服务端是不会处理这个连接请求的, 这个请求会被直接丢弃.

接口认识

1.创建套接字:
int socket(int domain, int type, int protocol)
  套接字类型是流式套接字, 协议类型是tcp协议;
2.绑定地址:
int bind(int sockfd, struct sockaddr *addr, socklen_t len);
3.开始监听
int listen(int sockfd, int backlog)
 sockfd: 描述符;   backlong:服务端能够在同一时间处理的最大连接数
套接字编程3(tcp)_第3张图片
3.客户端发送连接请求
int connect(int sockfd, struct sockaddr *srvaddr, socklen_t len)
 sockfd: 描述符;  srvaddr: 服务端地址信息;  len: 地址长度
 返回值: 成功返回0;  失败返回-1;

4.服务端获取新建连接
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
 sockfd: 监听套接字–服务端最早创建的套接字–只用于获取新建连接
 cliaddr: 新的连接的客户端地址信息;
 addrlen: 输入输出参数, 指定地址信息长度, 以及返回实际长度
 返回值: 新建连接的套接字描述符—往后与客户端的通信都通过这个描述符完成
5.收发数据
ssize_t send(int sockfd, void *data, int len, int flag);
 sockfd: 套接字描述符; data: 要发送的数据;
 len: 数据长度;  flag: 0;
 返回值: 成功返回实际发送的数据长度; 失败返回-1; 连接断开会触发异常;

ssize_t recv(int sockfd, void *buf, int len, int falg)
 sockfd: 描述符;  buf: 空间地址;
 len: 要接收的数据长度;  flag: 0;
 返回值: 成功返回实际接收的数据长度;  出错返回-1; 连接断开返回0;
tcp通信因为socket结构中包含完整五元组因此不需要指定地址
6.关闭套接字
int close(sockfd);

你可能感兴趣的:(网络)