TCP套接字编程

时间:2021-04-03 10:19:24

TCP套接字编程

TCP的三次握手,四次挥手图解

TCP套接字编程

三次握手:

1.确认目的设备存在于网络上;

2.确认目的设备有活动的服务,并且正在源客户端要使用的目的端口号上接受请求;

3.通知目的设备源客户端想要在该端口号上建立通信会话。

过程:

 

1. 客户端向服务器发送包含初始序列值的数据段,开启通信会话;

2. 服务器发送包含确认值的数据段,其值等于收到的序列值加 1,并加上其自身的同步序列值。该值比序列号大 1,因为 ACK 总是下一个预期字节或二进制八位数。通过此确认值,客户端可以将响应和上一次发送到服务器的数据段联接起来;

3. 发送带确认值的客户端响应,其值等于接受的序列值加 1。这便完成了整个建立连接的过程。

四次挥手:

1. 当客户端的数据流中没有其它要发送的数据时,它将发送带 FIN 标志设置的数据段;

2. 服务器发送 ACK 信息,确认收到从客户端发出的请求终止会话的 FIN 信息;

3. 服务器向客户端发送 FIN 信息,终止从服务器到客户端的会话;

4. 客户端发送 ACK 响应信息,确认收到从服务器发出的 FIN 信息。

注:FIN(表示结束) ACK(表示确认)

TCP通信的具体步骤:

● 服务器端流程

创建套接字(socket)

服务绑定(bind)

服务侦听(listen)

处理新到连接(accept)

数据收发(recv\send)

套接字关闭(close

● 客户端流程

① 客户端套接字创建(socket)

② 发起连接 (connect)

③  数据发收(send\recv)

 

图解:

TCP套接字编程

 

 

程序:

文件1:utili.h

#include<unistd.h>

#include<stdio.h>

#include<string.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

 

#define SERVER_PORT  9090

#define SERVER_IP    "192.168.2.252"

#define LISTEN_QUEUE  5

#define BUFFER_SIZE   255

 

文件2:Ser.cpp

#include"utili.h"

int main()

{

    int sockSer = socket(AF_INET, SOCK_STREAM, 0);//返回套接字的描述符

    if(sockSer == -1) //判断

    {

        perror("socket");

        return -1;

    }

 

    struct sockaddr_in  addrSer, addrCli;

    addrSer.sin_family = AF_INET; //协议、地址族

    addrSer.sin_port = htons(SERVER_PORT); //端口

    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

//IP地址

    int yes = 1;

    setsockopt(sockSer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));

 

    socklen_t  len = sizeof(struct sockaddr);

    int res = bind(sockSer,(struct sockaddr*)&addrSer, len); //绑定套接字

    if(res == -1)//判断

    {

        perror("bind");

        close(sockSer);

        return -1;

    }

 

    

    res = listen(sockSer, LISTEN_QUEUE);//帧听

    if(res == -1)

    {

        perror("listen");

        close(sockSer);

        return -1;

    }

    

    int sockConn;

    sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &len);//处理到新连接

    if(sockConn == -1)

    {

        printf("Server Accept Client Connect Fail.\n");

        close(sockSer);

        return -1;

    }

    else

    {

        printf("Server Accept Client Connect OK.\n");

        printf("Client IP:> %s\n",inet_ntoa(addrCli.sin_addr));

        printf("Client PORT:>%d\n",ntohs(addrCli.sin_port));

    }

 

    char sendbuf[BUFFER_SIZE];

    char recvbuf[BUFFER_SIZE];

    while(1)

    {

        printf("Ser:>");

        scanf("%s",sendbuf);

        send(sockConn, sendbuf, strlen(sendbuf)+1, 0);//发送数据

 

        recv(sockConn, recvbuf, BUFFER_SIZE, 0);//接收数据

        printf("CLi:>%s\n",recvbuf);

    }

    close(sockSer);//关闭服务器端

 

    return 0;

}

文件3:Cli.cpp

#include"utili.h"

 

int main()

{

    int sockCli = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in addrSer;

    addrSer.sin_family = AF_INET;

    addrSer.sin_port = htons(SERVER_PORT);

    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

 

    struct sockaddr_in addrCli;

    addrCli.sin_family = AF_INET;

    addrCli.sin_port = htons(7070);

    addrCli.sin_addr.s_addr = inet_addr("192.168.3.252");

 

    socklen_t len = sizeof(struct sockaddr);

    bind(sockCli, (struct sockaddr*)&addrCli, len);

    int res = connect(sockCli, (struct sockaddr*)&addrSer, len);

    if(res == -1)

    {

        printf("Client Connect Server Fail.\n");

        close(sockCli);

        return -1;

    }

    else

    {

        printf("Client Connect Server OK.\n");

    }

 

    char sendbuf[BUFFER_SIZE];

    char recvbuf[BUFFER_SIZE];

 

    while(1)

    {

        recv(sockCli, recvbuf, BUFFER_SIZE, 0);

        printf("Ser:>%s\n",recvbuf);

        printf("Cli:>");

        scanf("%s",sendbuf);

        send(sockCli, sendbuf, strlen(sendbuf)+1, 0);

    }

    close(sockCli);//关闭客户端

    return 0;

}