TCP
TCPTCP协议可靠性
TCP协议传输数据时会为每个字节分配一个序列号,通过这个序列号就可以判断数据是否重复到达以及数据是否丢失,还可以通过序列号对数据进行排序。另外,接收端每次接收到数据之后必须发送确认应答(ACK),如果在超时时间内没有发送应答信号(ACK),则TCP协议会认为数据没有送达,则会重新发送数据。
TCP协议判断数据是否损坏的方式是给每个数据段都添加校验和,接收端收到数据段进行校验,如果校验失败则丢弃已经损坏的数据段,也并不会进行确认应答,所以TCP协议会再次传输数据段。
因为通信可能是建立在不可靠的网络中以及网络层不可靠的传输机制,所以TCP协议中采用了一种*基于时钟的序列号握手机制*实现双方的有效连接,避免出现错误的连接初始化。
练习:主机A作为服务器,主机B作为客户端,主机A和主机B建立TCP连接,主机B可以向主机A发送消息
主机A
#include <sys/socket.h>
#include <netinet/in.h>
#include
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
//TCP服务器代码 ./xxx port
int main(int argc, char const *argv[])
{
//1.创建TCP套接字
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket == -1)
{
fprintf(stderr, "tcp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.绑定自身的IP地址和端口
struct sockaddr_inhost_addr;
host_addr.sin_family = AF_INET; //协议族,是固定的
host_addr.sin_port = htons(atoi(argv)); //目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = htonl(INADDR_ANY); //目标地址INADDR_ANY 这个宏是一个整数,所以需要使用htonl转换为网络字节序
bind(tcp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));
//3.设置监听队列最大容量是5
listen(tcp_socket,5);
//4.等待接受客户端的连接请求
struct sockaddr_inclient;
socklen_t client_len = sizeof(client);
int connect_fd = accept(tcp_socket,(struct sockaddr *)&client,&client_len); //会阻塞
char buf = {0};
//5.说明双方建立连接,此时可以接收数据
while(1)
{
read(connect_fd,buf,sizeof(buf));
printf("recv from [%s],data is = %s\n", inet_ntoa(client.sin_addr) ,buf);
bzero(buf,sizeof(buf));
}
return 0;
}主机B(客户端)
#include <sys/socket.h>
#include <netinet/in.h>
#include
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
//TCP客户端代码 ./xxx portIP
int main(int argc, char const *argv[])
{
//1.创建TCP套接字
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket == -1)
{
fprintf(stderr, "tcp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.发起连接请求,等待接受服务器接受连接
struct sockaddr_indest_addr;
dest_addr.sin_family = AF_INET; //协议族,是固定的
dest_addr.sin_port = htons(atoi(argv)); //服务器端口,必须转换为网络字节序
dest_addr.sin_addr.s_addr = inet_addr(argv); //服务器地址 "192.168.64.xxx"
int ret = connect(tcp_socket,(struct sockaddr *)&dest_addr,sizeof(dest_addr));
if (ret < 0)
{
fprintf(stderr, "connect error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
char buf = {0};
//3.说明双方建立连接,此时可以接收数据
while(1)
{
printf("请输入:");
scanf("%s",buf);
write(tcp_socket,buf,sizeof(buf));
bzero(buf,128);
}
return 0;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]