简述TCP/IP建立连接过程(附流程和代码)
前言:
TCP/IP 定义了计算机操作系统如何连入互联网,以及数据传输的标准。
TCP和IP是属于不同协议栈层的,只是这两个协议属于协议族里最重要的协议,所以协议栈或者模型以之命名了。
本段转载C语言中文网:TCP/IP 不是指一个协议,也不是 TCP 和 IP 这两个协议的合称,而是一个协议族,包括多个网络协议,比如 IP、ICMP(Internet Control Message Protocol,互联网控制报文协议)、TCP、HTTP(Hyper Text Transfer Protocol,超文本传输协议)、FTP(File Transfer Protocol,文件传输协议)、POP3(Post Office Protocol version 3,邮局协议)等。
正文:TCP/IP模型的连接过程:实质就是TCP通信的连接。
TCP(即传输控制协议)是一种面向连接的传输层协议,提供可靠的连接服务
tcp通信:采用三次握手建立连接:
三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。
服务器必须准备好接受外来的连接。这通过调用socket、 bind和listen函数来完成,称为被动打开(passive open)。
第一次握手:客户通过调用connect进行主动打开(active open)。这引起客户TCP发送一个SYN(表示同步)分节(SYN=J),它告诉服务器客户将在连接中发送到数据的初始序列号。并进入SYN_SEND状态,等待服务器的确认。//类似客户主动给公司打电话,公司这边手机响铃并显示来电号码(以便公司确认是不是自己的客户的电话号;
第二次握手:服务器必须确认客户的SYN,同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器以单个字节向客户发送SYN和对客户SYN的ACK(表示确认),此时服务器进入SYN_RECV状态。//公司确定是自己的客户的号码就接通这个电话号,并回应客户那边一声你好啊袁总;
第三次握手:客户收到服务器的SYN+ACK。向服务器发送确认分节,此分节发送完毕,客户服务器进入ESTABLISHED状态,完成三次握手。//客户收到公司的问候,回应你好啊王总,此刻可以两边都确定接通电话了,才能开始聊正事了;
TCP通信 编程流程(代码实现在最下方)
|
|
服务器端tcp通信 代码实现:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if(argc != 3)
{
printf("please input %s <ip> <port>n",argv[0]);
return -1;
}
//1.创建套接字 socket
int sockfd,acceptfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket err.");
return -1;
}
printf("socket ok %dn", sockfd);
//填充ipv4的通信结构体
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
//&serveraddr -->struct sockaddr_in *
//2.绑定套接字 bind (绑定自己的ip和端口,便于别人找到自己)
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind err.");
return -1;
}
printf("bind ok.n");
//3.listen 监听 将主动套接子变为被动等待
if (listen(sockfd, 5) < 0)
{
perror("listen err.");
return -1;
}
printf("listen ok.n");
//4.阻塞等待客户端链接,链接成功返回一个通信文件描述符 accept
acceptfd=accept(sockfd,NULL,NULL);
if(acceptfd < 0)
{
perror("accept err.");
return -1;
}
printf("accept ok.n");
//5.循环收发消息
char buf[128];
int recvbyte;
while(1)
{
//接收消息
recvbyte=recv(acceptfd,buf,sizeof(buf),0);
if(recvbyte < 0)
{
perror("recv err.");
return -1;
}else if(recvbyte == 0)
{
printf("client exit.n");
break;
}else
{
printf("buf:%sn",buf);
}
}
close(acceptfd);
close(sockfd);
return 0;
}
客户端tcp通信 代码实现
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
if(argc != 3)
{
printf("please input %s <ip> <port>n",argv[0]);
return -1;
}
//1.创建套接字 socket
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket err.");
return -1;
}
printf("socket ok %dn", sockfd);
//填充ipv4的通信结构体 服务器端ip和端口
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
//&serveraddr -->struct sockaddr_in *
//2.请求链接 connect
if (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("connect err.");
return -1;
}
printf("connect ok.n");
//3.循环收发消息
char buf[128];
int recvbyte;
while(1)
{
fgets(buf,sizeof(buf),stdin);
if(buf[strlen(buf)-1]=='n')
buf[strlen(buf)-1]='';
//发送消息
send(sockfd,buf,sizeof(buf),0);
}
close(sockfd);
return 0;
}