Linux网络编程

TCP目录

一、Internet(冷战时期的产物)的发展历史

二、网络模型

1、OSI七层理论模型

2、TCP/IP协议模型(协议族)

三、网络编程基础

1、套接字

2、IP地址

3、端口号——Port

4、字节序

小端字节序

大端字节序

主机字节序——host

网络字节序——network

字节序转换

四、TCP服务器

创建套接字---socket

绑定--bind

监听--listen

等待连接--accept

五、代码实现


  • 一、Internet(冷战时期的产物)的发展历史

    • 1937年,ARAP(阿帕网)问世,互联网雏形,NCP。
    • 1974年,TCP协议问世,不能保证数据准确交互。
    • 1983年,TCP/IP协议问世,能够实现不同类型计算机之间通信,保证数据传输准确性。
  • 二、网络模型

    • 协议:事先约定好的一种规则(协议对等)
    • 1、OSI七层理论模型

      • 物、数、网、传、会、表、应

Linux网络编程_第1张图片

        • 应用层:用户/应用程序使用网络的接口。
        • 表示层:对数据进行加密、解密。
        • 会话层:建立通信端点。
        • 传输层:实现点对点通信,保证数据传输的质量。进行差错检测。
        • 网络层:路由寻址。
        • 数据链路层:对数据进行帧格式的封装,进行纠错流控。--帧
        • 物理层:指定物理设备标准(网线、光纤接口类型等),屏蔽底层硬件的差异。--比特流
    • 2、TCP/IP协议模型(协议族)

Linux网络编程_第2张图片

      • 应用层:HTTP(超文本传输协议)+‘s’(加密)/FTP/STMP
      • 传输层:
        • TCP:
          • 面向连接的协议(打电话等),关心数据的确认、超时、重传(保证数据传输质量)。
          • 提供有序的、可靠的、全双工的、基于字节流的服务。
          • 应用场景:登录程序(登录账号密码),重要文件。
        • UDP:
          • 无连接的协议(寄信等)但是效率高
          • 应用场景:视频直播(抖音、快手)等流媒体,大型游戏。
      • 网络层:IP     ICMP    IGMP(组播、广播)
      • 网络接口层:SLIP    PPP  Ethernet    ARP

Linux网络编程_第3张图片

Linux网络编程_第4张图片

  • 3、三次握手

    • 第一次握手:建立连接时,客户端发送SYN包((SYN=i)到服务器,并进入SYN SEND状态,等待服务器确认;

      第二次握手:服务器收到SYN包,必须确认客户的SYN (ACK=i+1 ),同时自己也发送一个SYN包((SYN j)}即SYN+ACK包,此时服务器进入SYN_RECV状态;

      第三次握手:客户端收到服务器的SYN十ACK包,向服务器发送确认包ACK(ACK=j+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

  • 三、网络编程基础

  • 1、套接字

      • 网络中不同主机之间进行通信的两个端口的抽象,简化编程。
      • Linux提供了一个socket的套接口,给用户提供了一种使用Linux内核当中集成的各种网络协议。(用户态<--->转化)
      • 套接字的本质就是文件描述符。
    • 2、IP地址

      • IPV4———4个字节
        • 1111 1111 1011 1111  1101 1111 1111 1111
        • 点分十进制:255.191.223.255
        • inet_addr("192.168.87.64")————将点分十进制的IP地址转换网络字节序的二进制形式。
      • IPV6———16个字节
    • 3、端口号——Port

      • unsigned short —— 0—65535
        • 1-1024:系统保留端口
        • 1025-5000:常用应用程序端口
        • 5001-65535:用户自定义端口
    • 4、字节序

      • 小端字节序

        • 当存储多字节数据时,数据的低位放到低地址空间中。——低低小
          • unsigned int a = 0x11223344;
          • unsigned char *p = (unsigned char *)&a;
          • if(*p == 0x44)
            • printf("小端\n");
          • else
            • printf("大端\n");
      • 大端字节序

      • 主机字节序——host

      • 网络字节序——network

      • 字节序转换

        • htons()将16位(unsigned short)主机字节顺序转网络字节顺序
        • ntohs()将16位(unsigned short)数量从网络字节顺序转主机字节顺序
        • htonl()将32位(unsigned long)整数从主机字节顺序转换为网络字节顺序
        • ntohl()将32位(unsigned long)数量从网络字节顺序转换为主机字节顺序

Linux网络编程_第5张图片

  • 四、TCP服务器

    • sudo service network-manager restart----重启网络服务
    • socket->bind->listen->accept->read/write->close
    • 创建套接字---socket

      • #include 
      • #include  
      • int socket(int domain, int type, int protocol);
      • 功能:在内核当中创建一个端点,并且返回一个文件描述符指向该端点。
      • 参数:
        • domain:
          • AF_UNIX:本地通信
          • AF_INET:网络通信IPV4
        • type
          • SOCK_STREAM:唯一与TCP对应————流式套接字
          • SOCK_DGRAM:唯一与UDP对应————数据报套接字
          • SOCK_RAM:原始套接字
        • protocol:一般传0
    • 绑定--bind

      • #include 
      • #include  
      • int bind(int sockfd, const struct sockaddr*addr, socklen_t addrlen);
      • 功能:为socket所指向套接字分配addr结构中所指定的IP地址
      • 参数:
        • sockfd:socket创建的套接字文件描述符
        • addr  :要绑定的地址
        • addrlen:地址结构体的长度
        • 结构体
          struct sockaddr {
           sa_family_t sa_family; 
          char        sa_data[14];         
           }      
          
          #include      
           #include       
          #include  /* superset of previous */  
          struct sockaddr_in {                  //man  7 ip
          sa_family_t    sin_family;                    /* address family: AF_INET */
          in_port_t      sin_port;                     /* port in network byte order */ 
          struct in_addr sin_addr;                      /* internet address */         
           };    /* Internet address. */ 
          
          struct in_addr { 
          uint32_t       s_addr;     /* address in network byte order */     
           }; 
          struct sockaddr_in saddr;    
          saddr.sin_family = AF_INET;    
          saddr.sin_port   = htons(8888);//将8888转换成网络字节序    
          saddr.sin_addr.s_addr = inet_addr("192.168.7.26"); 
          bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr))  
          

  • 返回值:  成功:返回0        失败:返回-1
    • 监听--listen

      • #include          /* See NOTES */
      • #include
      • int listen(int sockfd, int backlog);
      • 功能:让内核将绑定之后的套接字挂起,并且设置监听队列。
      • 参数:
        •   sockfd:绑定之后的流式套接字(SOCK_STREAM).
        •   backlog:队列长度   > 0
        • 返回值:
          •   成功:0
          •   失败:-1
    • 等待连接--accept

      • #include           /* See NOTES */
      •  #include
      • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      • 功能:阻塞等待连接,如果sockfd所对应的监听队列里面有连接请求,accept处理队列队头的请求:创建一个新的套接字文件描述(连接套接字/读写套接字)符与该请求一一对应。
      • 参数:
        • sockfd:监听套接字
        • addr:用于保存对端的IP地址 ---->NULL---->不保存对端的IP地址
        • addrlen:地址结构体的长度---->长度一定要先计算出来
      • 返回值:
        • 成功:返回一个新的套接字文件描述符(连接/读写套接字)与新连接的客户端一一对应
        • 失败:-1
      • * read 去读accpet返回的连接套接字(connfd)时
        • 如果connfd对应的读缓冲区没有数据  ----read 阻塞
        • 如果connfd对应的读缓冲区有数据    ----read 解除阻塞 并且返回实际读到的字节数
        • 如果connfd对应的客户端断开连接    ----read 解除阻塞 并且返回0
      • connect函数

        • #include /* See NOTES */
        • #include
        • int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
        • 功能:系统调用将文件描述符sockfd引用的套接字连接到由addr指定的地址。
        • connect 不会像accept一样返还新的连接套接字
        • 参数
          • sockfd:标识一个套接字。
          • serv_addr:套接字s想要连接的主机地址和端口号。
          • addrlen:name缓冲区的长度。

      五、代码实现

  • #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char *argv[])
    { 
        //创建套接字
        int sockfd = socket(AF_INET,SOCK_STREAM,0);
        if(-1 == socket)
        {
            perror("socket");
            return -1;
        }
        else
            printf("创建成功\n");
        //绑定
        struct sockaddr_in saddr;
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(8888);
        saddr.sin_addr.s_addr = inet_addr("192.168.5.123");
        if(-1 == bind(sockfd, (struct sockaddr*)&saddr,sizeof(saddr)))
        {
            perror("bind");
            return -1;
        }
        else
            printf("绑定成功\n");
    
        //监听
        if(-1 == listen(sockfd,8))
        {
            perror("listen error\n");
            return -1;
        }
        else 
            printf("listen success\n");
    
        //连接
        struct sockaddr_in caddr;
        int addrlen = sizeof(caddr);
        int connfd = accept(sockfd, (struct sockaddr*)&caddr, &addrlen);
        if(-1 == connfd)
        {
            perror("accept error");
            return -1;
        }
        else
            printf("connfd success!!!!!!!\n");
        printf("ip:%s  port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        char buf[64] = {0};
        int ret = read(connfd, buf, sizeof(buf)-1);
    
        printf("ret: %d  buf: %s\n" ,ret ,buf);
        return 0;
    }
    

    相关参考以及代码:

  • TCP服务器客户端的搭建,以及客户端连接服务器发送信息

  • UDP客户端和服务端的搭建

  • TCP客户端从服务器进行图片下载

  • Linux网络编程创建服务器和客户端建立连接和传输信息-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/only_write_bug/article/details/134730616?spm=1001.2014.3001.5501

网络编程UDP客户端、服务端的搭建-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/only_write_bug/article/details/134783207?spm=1001.2014.3001.5501Linux网络编程客户端从服务端下载图片-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/only_write_bug/article/details/134736467?spm=1001.2014.3001.5501

你可能感兴趣的:(网络,tcp/ip,tcp)