linux网络编程基础

1、TCP/IP协议
传输控制/网际协议(Transfer Control Protocol/Internet Protocol) 又称作网络通讯协议
四个层次:网络接口层、网际层、传输层、应用层

2、网络编程常用函数:
网络编程头文件:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>

/*****************socket() -- 创建套接字*********************/
    int socket(int domain, int type, int protocol);
    domain是地址族
        PF_INET  // internet 协议 // 	AF_INET
        PF_UNIX // unix internal协议
        PF_NS      // Xerox NS协议
        PF_IMPLINK  // Interface Message协议
    type //套接字类型
       SOCK_STREAM   // 流式套接字
       SOCK_DGRAM    // 数据报套接字	SOCK_RAW     //  原始套接字
    protocol 参数通常置为0
    返回值:
        成功:套接字,linux系统下特殊的文件描述符
        失败:-1(系统调用失败都是-1,错误码保存在进程的全局变量errno中)
        
    例:int sockfd = socket(PF_INET, SOCK_STREAM, 0);

        
        
/*****************bind() -- 绑定本机地址和端口*********************/			

    int bind(int sockfd, struct sockaddr *my_addr, int addrlen) ; 			
    头文件:
    #include <sys/types.h>
    #include <sys/socket.h>
    sockfd: socket调用返回的文件描述符  
    addrlen: sockaddr地址结构的长度			返回值:0或-1
    
    例:int ret = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
    
    Internet协议地址结构
    struct sockaddr_in  // struct sockaddr
    {           
         u_short sin_family;      // 地址族, AF_INET,2 bytes
        u_short sin_port;      // 端口,2 bytes
        struct in_addr sin_addr;  // IPV4地址,4 bytes 	  // .sin_addr.s_addr = 
        char sin_zero[8];       // 8 bytes unused,作为填充
    }; 
    
    端口号:1-65535,其中0不使用
        1-1023: 系统端口,这些端口只有系统特许的进程才能使用;
        1024-5000: 一般的应用程序使用1024到4999来进行通讯;
        5001-65535: 服务器(非特权)端口,用来给用户自定义端口.

    地址结构的一般用法:
    
    1、 定义一个struct sockaddr_in类型的变量并清空
        struct sockaddr_in myaddr;
        memset(&myaddr, 0, sizeof(myaddr));

    2、 填充地址信息
        myaddr.sin_family = PF_INET;
        myaddr.sin_port = htons(8888);  //8888 error
        //myaddr.sin_addr.s_addr = inet_addr(“192.168.1.100”);  服务器中一般填 INADDR_ANY
        myaddr.sin_addr.s_addr = INADDR_ANY;
        myaddr.sin_zero = {0};

    3、 将该变量强制转换为struct sockaddr类型在函数中使用
        bind(listenfd, (struct sockaddr*)(&myaddr), sizeof(myaddr));

    
    
/*****************listen() -- 设置监听套接字*********************/
    
    int listen (int sockfd, int backlog);
    sockfd:监听连接的套接字
    backlog:
        指定了正在等待连接的最大队列长度,它的作用在于处理可能同时出现的几个连接请求。
        DoS(拒绝服务)攻击即利用了这个原理,非法的连接占用了全部的连接数,造成正常的连接请求被拒绝。
    返回值: 0 或 -1

    完成listen()调用后,socket变成了监听socket(listening socket).

    
/*****************accept() -- 接受TCP客户端连接*********************/	
        
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ;
    头文件
        #include <sys/types.h>
        #include <sys/socket.h>  
    sockfd : 监听套接字 
    addr : 对方地址
    addrlen 长度地址
    返回值:已建立好连接的套接字(读写套接字)或-1
    
    listen()和accept()是TCP服务器端使用的函数
    

/*****************connect() -- 建立连接*********************/

    int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
    头文件:
        #include <sys/types.h>
        #include <sys/socket.h>  
    sockfd : socket返回的文件描述符
    serv_addr : 服务器端的地址信息  
    addrlen : serv_addr的长度 
    返回值:0 或 -1
    
    connect()是客户端使用的系统调用
    

/*****************recv(),read() -- 数据接收*********************/	
    
    ssize_t  recv(int  socket,  const  void  *buffer,  size_t  length, int flags);
    返回值:
        成功:实际接收的字节数
        失败:-1, 并设置errno
    头文件:
        #include <sys/socket.h>
    buffer : 发送缓冲区首地址
    length : 发送的字节数
    flags : 接收方式(通常为0)

    ssize_t read(int fd, void *buf, size_t count);


/*****************send(),write() -- 数据发送*********************/	

    ssize_t  send(int  socket,  const  void  *buffer,  size_t  length, int flags);
    返回值:
        成功:实际发送的字节数
        失败:-1, 并设置errno
    头文件:
        #include <sys/socket.h>
    buffer : 发送缓冲区首地址
    length : 发送的字节数
    flags : 发送方式(通常为0)

    ssize_t write(int fd, const void *buf, size_t count);


/*****************close() -- 关闭套接字*********************/
    
    int close(int sockfd);
    关闭双向通讯;
    
    
    
TCP服务器端流程:
    socket -> bind -> lisent-> accept -> send/recv -> close(关闭后回到accept之前)

TCP客户端流程:
    socket -> bind(可选) -> connect -> send/recv -> close



循环服务器模型:
    TCP服务器
        1、 TCP服务器端运行后等待客户端的连接请求
        2、 TCP服务器接受一个客户端的连接后开始处理,完成了客户的所有请求后断开连接
        3、 TCP循环服务器一次只能处理一个客户端的请求
        4、 只有在当前客户的所有请求都完成后,服务器才能处理下一个客户的连接/服务请求
        5、 如果某个客户端一直占用服务器资源,那么其它的客户端都不能被处理。TCP服务器一般很少采用循环服务器模型

TCP循环服务器流程如下:
    socket(...);
    bind(...);
    listen(...);
    while(1)
    {
        accept(...);
        while(1)
        {
            recv(...);
            process(...);
            send(...);
        }
        close(...);
    }

linux网络编程基础
http://example.com/2020/10/15/linux网络编程基础/
作者
HaoDuck
发布于
2020年10月15日
许可协议