网络编程:TCP

本文详细介绍了TCP协议的基础概念,包括其提供的面向连接的可靠服务特点、三次握手和四次挥手的过程,以及TCP的状态转换机制。此外,还提供了TCP编程的具体流程和实例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、TCP协议提供的是面向连接的可靠的流式服务

即有发送缓冲区、接收缓冲区,发送次数和接收次数不一定对等。报头长,成本高,需要搭载更多的数据。

二、三次握手建立连接与四次挥手断开连接

1.三次握手

这里写图片描述
通过对ACK的确认,建立可靠连接。有超时重传机制

2.四次挥手

这里写图片描述
有可能服务器处理数据的时间较短,即三次挥手

3.状态图

这里写图片描述

    TIME_WAIT 状态: 出现在主动发起断开链接请求的一端
    意义:1、保证可靠的终止 TCP 链接
         2、保证迟来的数据报能被识别并丢弃
4.TCP状态转移过程

这里写图片描述

红线: 客户端发起链接 
绿线: 服务器接收链接
蓝线: 主动断开链接的过程 
紫线: 被动断开链接的过程
5.TCP报头

这里写图片描述

三、TCP 的编程流程:

server: socket      bind    listen  accept  recv/send   close client:       socket  /*bind*/          
connect recv/send   close

int socket(int domain, int type, int protocol);

    domain::    协议簇 AF_INET
    type::  选择协议    SOCK_STREAM(tcp)    SOCK_DGRAM(udp) 
    protocol:: 0

int bind(int sockfd, struct sockaddr *addr, int addrlen);

addr::  指定 IP 地址和端口号
struct  sockaddr_in
{
    sa_family_t sin_family; //  地址簇 AF_INET

u_int16_t   sin_port; //  端口号   网络字节序(大端模式) PC 机(小端模式) struct   in_addr sin_addr; //IP 地址
}

struct in_addr
{
    u_int32_t   s_addr; //  IP 地址最终的表示
}

int listen(int sockfd, int size);

int accept(int  sockfd, struct  sockaddr *addr, int *addrlen);
返回值:    获取到的和客户端连接的文件描述符
addr:;  记录客户端的 IP 地址和端口号

int connect(int sockfd, struct sockaddr* addr, int addrlen);

addr::  要连接的服务器的 IP 地址和端口号

四、代码实现

1.服务器端
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

void main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);

    struct sockaddr_in ser ,cli;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1"); 

    int res = bind(sockfd,(struct sockaddr *)&ser, sizeof(ser));
    assert(res != -1);


    listen(sockfd,5);
    while(1)
    {
        int len = sizeof(cli);
        int c = accept(sockfd,(struct sockaddr*)&cli,&len);
        printf("accept success!\n");
        assert(c != -1);

        char buff[128] = {0};
        recv(c,buff,127,0);
        if(strncmp(buff,"end",3)== 0)
        {
            close(c);
            break;
        }
        printf("recv::%s\n",buff);
        send(c,"I Know",strlen("I Know"),0);
        close(c);
    }
    close(sockfd);
}

2.客户端

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

void main()
{

    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd != -1);


    struct sockaddr_in ser,cli;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr *)&ser,sizeof(ser));
    assert(res != -1);
    int key=1;
    while(key)
    {
        char buff[128]={0};
        fgets(buff,128,stdin);
        send(sockfd,buff,strlen(buff),0);
        printf("success!\n");
        if(strncmp(buff,"end",3)==0)
        {
            key = 0;
        }
        recv(sockfd,buff,127,0);
        printf("recv:: %s\n",buff);
    }

    close(sockfd);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值