简述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;
}