计算机网络——socket_tcp&应用层协议

写代码的时候,先应该调用函数,其次再考虑用函数时该如何传参

TCP编程流程

计算机网络——socket_tcp&应用层协议_第1张图片
在这里插入图片描述
计算机网络——socket_tcp&应用层协议_第2张图片
监听:listen 发送数据:send 发起连接connect 接收数据:recv

监听:

int listen(int sockfd, int backlog);

sockfd : 侦听套接字,socket函数的返回值
backlog: 已完成连接队列的大小
1.共识:
当我们调用了listen函数之后,也就是告诉内核,当中程序可以接收新的连接了,换句话说,也就是可以完成三次握手的过程了:
三次握手时网络协议栈完成的事情,程序员不需要干预,连接建立的过程实在内核当中完成的
计算机网络——socket_tcp&应用层协议_第3张图片
backlog: 已完成连接队列的大小

接收新连接

int accept(int sockfd, struct sockaddr* addr, sockaddr* addr, socklent_t* addrlen);

sockfd:侦听套接字,socket函数的返回值
addr: 对端的地址信息,客户端的地址信息
addrlen:对端的地址信息,客户端地址信息长度
返回值:
正常:返回的时为新连接创建出来的套接字
失败: 小于0
**注意:**获取新连接是从“已完成连接队列”当中获取新连接
如果已完成连接队列为空,调用该接口,执行流会被阻塞
发起连接:

int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);

sockfd: 客户端调用socket创建出来的套接字描述符
addr:要连接的服务端的地址信息
addrlen:地址信息长度
发送数据:

ssize_t send(int sockfd, const void* buf, size_t len, int flags);

sockfd:
客户端:客户端调用socket函数创建出来的套接字描述符
服务端:accept函数的返回值
buf: 待发送的数据
len : 发送数据的长度
flags: 0 阻塞发送
接收数据:

ssize_t recv(int sockfd, void* buf, size_t len,int flags);

sockfd:
客户端:客户端调用socket函创建出来的套接字描述符
服务端:accept函数的返回值
buf:接收数据使用缓冲区
len: 最大接收能力
flags: 0 阻塞接收
返回值:
小于0:发送失败
等于0:对端关闭了连接
大于0:接收了多少字节数据

客户端:创建套接字 发起连接 发送数据 接收数据 关闭套接字
服务端: 创建套接字 绑定地址信息 监听 获取新连接 接收数据 发送数据 关闭套接字
1.如何查看当前程序是否在侦听端口或者如何知道某个端口是否在侦听
netstat -anp | grep [port]
2.accept 在阻塞
3.win命令telnet 命令,可以验证端口是否在侦听(或者说telnet命令可以完成三次握手)

应用层

1.自定制协议
2.HTTP协议
计算机网络——socket_tcp&应用层协议_第4张图片
1.accept函数放到while(1)的外面,单执行流的时候,accept只能被调用一次,也就是意味着服务端的程序只能获取一个新的连接,后续的客户端及时和当前服务端完成了三次握手的过程,建立了新的连接,服务端程序也是没有办法在调用到accept函数来接收回来了
2.accept函数放到while(1)的里面,当执行流的之后,每次循环,服务端程序都要接收一个新的连接,对于每一个客户端都稚嫩那个数据收发一次:当服务端进入到下一次循环的时候,就要接收新的连接了
计算机网络——socket_tcp&应用层协议_第5张图片

抓包工具

1.win
wireshark
2.linux
tcpdump
前提:抓取的数据包时从网卡设备当中抓取的
tcpdump -i any port [端口] -s 0 -w 122.dat
使用root用户抓包
——————————————————————————————————————————
1.应用层
1.1 自定制协议
1.2 HTTP协议
2.传输层
2.1 UDP协议
2.2 TCP协议

自定制协议

1.自定制协议是工作在应用层,被程序员定义出来的协议
2.TCP特性:面向字节流

send(sockfd, "i", 1, 0);

自定制协议:就是在应用层对要传输的数据,进行数据格式的约定,消息的发送方和接收方都遵守该约定
计算机网络——socket_tcp&应用层协议_第6张图片
计算机网络——socket_tcp&应用层协议_第7张图片
tcp粘包问题,我们需要在应用层自定制协议,自定制协议增加报头和分隔符
【定长报头(数据长度)】 + 数据
【定长报头】 + 数据 + 分隔符
【不定长的报头】 + 数据 + 分割符【不定长的报头】 + 数据 + 分割符
对于定长报头而言,数据的收发都是遵守这样的约定的
对于不定长的报头,由于数据也不是定长的,所以引入分隔符,而分隔符在这里面起到的作用是标识当前数据的尾部,当我们接收方和发送方都严格按照自定制协议进程传输的时候,TCP连接当中传输TCP数据都是【报头】 + 数据+ 分隔符的方式,所以,找到分隔符还可以找到下一条数据的开始

序列化:将对象转化成为二进制
反序列化:将二进制转化成为对象
在这里插入图片描述
https://www.baidu.com/
HTTP协议:
http:协议方案名
user:pass我的:用户名和密码
www.baidu.com: 域名–》ip地址
/dir/index.html:带层次的文件路径
“/”:并不是linux操作系统的根目录,而是http服务器的逻辑根目录
key = value
urlencode:url编码,对于有通俗意义的符号进行编码
C++ ==> C%2B%2B
编码就是将符号转化成为16进制的字符,进行传输
%就是提示服务器,后面传输的内容是经过URLendcode
urldecode:url解码
不同的key = value的键值对是使用“&”进行相连接的
key = value : 放在url当中提交给服务端的内容
ch1:片段标识符

1.HTTP协议在传输层使用的协议是TCP协议
2.HTTP数据包格式
请求:
请求首行
请求方法 资源路径 协议版本\r\n HTTP/1.0 HTTP/1.1 HTTP/2
请求体
key: value\r\n
空行\r\n
正文
请求方法
Get:从服务器获取数据,但是现在也可以给服务器去提交key = value形式的数据,只不过提交的数据是在url当中的
Post:向服务器提交数据,提交的数据是在正文当中的
Post方法比Get方法更加私密,想要安全,则需要ssl加密 计算机网络——socket_tcp&应用层协议_第8张图片
请求体:
Host:请求的主机名称
Connection:keep-alive(长连接)
User-Agent:浏览器的版本信息和操作者系统的信息
Content-Type:正文类型
Accept-Encoding:能够接收的编码格式
Accept-Language:能够接收的语言
计算机网络——socket_tcp&应用层协议_第9张图片
1.对于应用层调用send接口,只是负责将数据放到TCP的发送缓冲区当中,至于TCP如何发送和之前应用层的发送规律没有任何关系;
2.面向字节流好处是对于数据可以灵活的发送和接收,但是也带来了TCP粘包的问题(对于消息的接收方而言,就不好区分,客户端应用层发送的每一条数据)

你可能感兴趣的:(socket,linux,http,网络)