嵌入式(day33)TCP协议
1)TCP的特点
1. 面向数据流
2. 有连接(通信之前必须建立连接)
3. 安全可靠的传输机制
4. 机制复杂,网络资源开销大
5. 本质只能实现一对一的通信(使用TCP并发方式可实现一对多通信)
2)TCP三次握手和四次挥手机制
TCP三次握手:TCP建立连接时,需要进行三次握手,为了确保收发双方通信之前都已准备就绪。

tcp四次挥手:其断开时,需要进行四次挥手,确保断开连接前双方已通信结束

3)TCP的编程流程

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:请求与服务端建立连接
参数:
sockfd:套接字
addr:要连接的服务端的地址信息
addrlen:服务端地址大小
返回值:
成功:0、 失败:-1
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送网络数据
参数:
sockfd:网络套接字
buf:要发送的数据首地址
len:发送的字节数
flags:0:按照默认方式发送
返回值:
成功:实际发送的字节数。失败:-1
int listen(int sockfd, int backlog);
功能:监听建立三次握手的客户端
参数:
sockfd:监听套接字
backlog:最大允许监听的客户端个数
返回值:
成功:0、失败:-1
int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
功能:接收建立三次握手的客户端,并产生一个通讯套接字
参数:
socket:监听套接字
address:客户端的地址信息
address_len:客户端地址长的指针
返回值:
成功:通讯套接字。失败:-1
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:从网络套接字上接收数据
参数:
sockfd:通讯套接字
buf:存放接收数据的首地址
len:期望接收到的字节数
flag:0:默认方式接收(阻塞)
返回值:
成功:实际接收到的字节数
失败:-1
对方断开连接:0
客户端
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <sys/types.h> /* See NOTES */
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
struct msg
{
char text[128];
};
int main(int argc,const char *argv[])
{
//socket
//connect
//send
//recv
//close
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(socket < 0)
{
perror("socket error");
return -1;
}
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(50000);
seraddr.sin_addr.s_addr = inet_addr("192.168.0.155");
int ret = connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret < 0)
{
perror("connect error");
return -1;
}
// struct msg mymsg;
// strcpy(mymsg.text,"hello world");
char buff[1024] = {0};
// while(1)
// {
fgets(buff,sizeof(buff),stdin);
ssize_t cnt = send(sockfd,buff,strlen(buff),0);
if(cnt < 0)
{
perror("send error");
return -1;
}
printf("cnt = %ld\n",cnt);
// }
close(sockfd);
return 0;
}
服务端
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <sys/types.h> /* See NOTES */
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
int main(int argc,const char *argv[])
{
//socket
//bind
//listen
//accpet
//rece
//send
//close
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(socket < 0)
{
perror("socket error");
return -1;
}
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(50000);
seraddr.sin_addr.s_addr = inet_addr("192.168.0.155");
int ret = bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
if(ret < 0)
{
perror("bind error");
return -1;
}
ret == listen(sockfd,10);
if(ret < 0)
{
perror("listen error");
return -1;
}
int connfd = accept(sockfd,NULL,NULL);
if(connfd < 0)
{
perror("connfd error");
return -1;
}
while(1)
{
char buff[1024] = {0};
memset(buff,0,sizeof(buff));
ssize_t cnt = recv(connfd,buff,sizeof(buff),0);
if(cnt < 0)
{
printf("recv error");
return -1;
}
printf("cnt = %ld, buff = %s\n",cnt,buff);
}
close(connfd);
close(sockfd);
return 0;
}
4) TCP粘包问题
TCP粘包问题:发送方应用层发送的多包数据,将来在接收方可能一次读到,多包数据产生了粘连。
原因:
1. 发送方速度较快,TCP底层可能对多包数据进行重新组帧;
2. 接收方数据处理速度较慢,导致多包数据在接收缓冲区缓存,应用层读时,一次将多包数据读出。
解决粘包问题的常用方法:
1. 调整发送速率
2. 发送指定大小,将来接收方也接受指定大小。
结构体
注意:
1. 跨平台之间的数据传输时,注意结构体对齐问题。
struct a
{
char a;
int b;
long c;
};
32bits平台《--》64位平台
3. 应用层位发送的数据增加分隔符,利用分隔符解析
hello world\nhow are you\n
4. 封装自定义数据帧格式进行发送(协议),严格根据协议进行解析。
AA C0 00 00 00 F0 00 BB 10 A0 00 00 00 10 校验 BB AA C0 00 00 00 F0 00 BB 10 A0 00 00 00 10 校验 BB
帧头:AA
帧尾:BB
有效数据长度:C0
有效数据:00 00 00 F0 00 BB 10 A0 00 00 00 10
校验:
8位和校验
16位和校验
CRC校验
5) TCP的其他机制
TCP头部的标志位:
SYN:请求建立连接标志位
ACK:响应报文标志位
PSH:携带数据标志位,通知接收方该从缓冲区读数据
FIN:请求断开连接标志位
RST:复位标志位
URG:紧急数据标志位

机制:
安全可靠:
1. 三次握手和四次挥手机制
2. 应答机制:TCP对于每一包数据都会给出相应的应答。发送数据时序列号表示这包数据的起始编号,响应报文中的确认号是接收方收到的最后一个字节编号+1。
3. 超时重传机制:当数据发送出去等待指定时间没有收到响应,此时认为这包数据丢失则进行重传。
4. 滑动窗口机制:一段缓冲区,缓存TCP已发送未收到响应,准备发送等数据
提高效率:
1. 延迟应答机制:发送数据的同时可以等待应答
2. 流量控制机制:结合TCP头部的窗口大小,动态调整发送速率。
3. 捎带应答机制:ACK报文可能和应用层的数据同时发送

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)