网络编程:TCP

来源:互联网 发布:记事本软件无弹窗下载 编辑:程序博客网 时间:2024/06/06 01:59

一、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_INETu_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);}