zoukankan      html  css  js  c++  java
  • linux网络编程

    A: osi七层:

               应用层                     

       表示层                     

       会话层                     

       ********************************

       传输层                       

       网络层                       

       数据链路层                   

       物理层

    a1: 传输层协议:

                 tcp(传输控制协议):可靠的,面向连接的(连接,通信,断开连接)

        ** tcp连接(三次握手连接)

       tcp四次握手连接

     udp(用户数据报协议):面向无连接,不安全

     端口号(默认80):找到接收数据的地址

                               IP:找到接收数据的机器

    a2: 网络层协议:ip(网际协议)

    a3: 数据链路层标准:以太网

    B: 主机字节序和网络字节序:

            低位存放低地址,小端对齐(主机字节序)

    低位存放高地址,大端对齐(网络字节序),使用htonl,htons,ntohs,ntohl函数,h:host     to:change        n:network      s:short       l:long

    C: IP地址的转换:

            字符串类型:192.168.2.123

    数值类型:

        in_addr_t inet_addr(const char *cp);

       功能:将字符串类型ip地址转换为数值型ip地址,并且转换字节序

       参数:cp----字符串类型ip地址

       返回值:数值型ip地址

    in_addr_t inet_network(const char *cp);

                   功能、参数、返回值同上,不同的是未做字节序转换

    char *inet_ntoa(struct in_addr in);

                   功能:将数值类型ip地址转为字符串型ip地址

       参数:in     

             struct in_addr

     {

      in_addr_t s_addr;

     };

    D: 文件描述符:

           open  close  read  write  //linux提供的系统调用

       分配原则:当前系统最小,并空闲的

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

         功能:从文件读取内容

     参数:fd----文件描述符

           buf----存放读取数据的缓冲区

       count----缓冲区的大小

     返回值:读取的字节数     0----读取结束    -1----失败

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

             功能:往文件写入数据

     参数:fd----文件描述符

           buf----写入数据的缓冲区

       count----缓冲区的大小

     返回值:写入数据的字节数    -1-----失败

    E: 被动端/服务端函数:

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

          功能:创建网络版的文件描述符(套接字)

      参数:domain-----AF_INET(ipv4协议族)

            type-----套接字的类型   SOCK_STREAM=面向连接(tcp协议)               SOCK_DGRAM=面向无连接(udp协议)

            protocol:协议    0---根据协议族和套接字类型自动填写协议

                      或者:IPPROTO_TCP  IPPROTO_UDP

       返回值:套接字      -1-----失败

    e2:   int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

          功能:将IP地址和端口号与套接字绑定

           接收者:只能接收绑定地址为目的地址,绑定端口号为目的端口号的报文

       发送者:设置源ip地址和源端口号

      参数:sockfd----套接字

            addr:

         struct sockaddr_in {

            short sin_family;   //协议族:AF_INET

         short sin_port;   //端口号

         short in_addr sin_addr;   //ip地址

         }

    addrlen------地址结构体的长度

       返回值:0---成功   -1----失败

    e3:   int listen(int sockfd, int backlog);

              功能:将套接字的状态修改为被动态,并建议设置内核中的完成连接队列的长度

      参数:sockfd----套接字

            backlog----建议值

      返回值:0---成功   -1----失败

    e4:   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

              功能:阻塞函数,从内核的连接完成队列中取出一个连接状态

      参数:sockfd----套接字

            addr----出参,带回主动端的ip地址和端口号

    addrlen------地址结构体的长度

      返回值:用于通信的套接字    -1----失败   

    F: 主动端/客户端函数:

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

    f2:    int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

              功能:发起三次握手连接

          参数:sockfd----套接字

                addr---被动端的ip地址和端口号

        addrlen----地址结构体长度

          返回值:0---成功   -1----失败

    注意:

         read读取tcp数据时返回值为0表示写端/发送端关闭

     当接收端关闭,发送数据端将被信号SIGPIPE杀死

    H: 接收数据(属性都默认是0):

       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);

    I: 线程操作时注意:

           临界资源(多个进程(共享内存)或线程访问的资源(局部变量、全局变量))和互斥(在同一时间只有并仅有一个进程或线程可以访问临界资源)

    J: 多路IO:

       j1: select监听的步骤:

              1.将监听的文件描述符添加到文件描述符集合 中

          eg:fd_set rdfds;

          FD_ZERO(&rdfds);

      FD_SET(0,&rdfds);

      FD_SET(confd,&rdfds);

       2.调用select监听活跃的文件描述符

       3.判断监听的文件描述符是否活跃

           eg:FD_ISSET(0,&rdfds);

               int select(int nfds,

          fd_set *readfds,

      fd_set *writefds,

      fd_set *exceptfds,

      struct timeval *timeout);

       功能:监听多个I/O端口(文件描述符),采用轮询的方式监听文件描述符,所以随着监听的文件描述符的增多而使效率降低

       参数:nfds---监听文件描述符中的最大值+1

             readfds、writefds、exceptfds(执行的文件描述符)---监听的文件描述符的集合。这三个文集描述符既是入参(监听的文件描述符集合),也是出参(带回活跃的文件描述符集合)

     timeout----监听超时的时间

    返回值:监听文件描述符集合中活跃的文件描述符的个数        -1-----失败

          

    操作文件描述符集合:

      将文件描述符fd从文件描述符集合set中删除:

    void FD_CLR(int fd, fd_set *set);

      判断文件描述符fd在文件描述符集合set中:

    int  FD_ISSET(int fd, fd_set *set);

       1----存在   0------不存在

      将文件描述符fd添加到文件描述符集合set中:

    void FD_SET(int fd, fd_set *set);

      将文件描述符集合set清空:

    void FD_ZERO(fd_set *set);

       j2: poll()工作模式和select相同---轮询监听:

          

           int poll(struct pollfd fds[],

                nfds_t nfds,

    int timeout);

      参数:fds---监听的文件描述符的数组

       struct pollfd {

       int   fd;         /*监听的文件描述符*/

       short events;     /*感兴趣的事件*/

       short revents;    /*活跃的事件*/

      };

            nfds---数组的个数

    timeout---超时时间,不超时就是 -1

       返回值:监听文件描述符集合中活跃的文件描述符的个数        -1----    -失败

       j3: epoll():

              工作模式:只关心活跃的文件描述符,所以它不会随着监听文件描述符的增多而效率下降

                int epoll_create(int size);

       功能:创建epoll文件描述符

       参数:size----epoll通知内核epoll最多监听的文件描述符的个数

       返回值:返回文件描述符     -1-----失败

    int epoll_ctl(int epfd,

                  int op,

      int fd,

      struct epoll_event *event);

    功能:epoll操作监听的文件描述符

    参数:epfd----epoll文件描述符

          op----操作:EPOLL_CTL_ADD(将文件描述符添加到epoll中)

                  EPOLL_CTL_MOD(修改在epoll监听的文件描述符的事件)

      EPOLL_CTL_DEL(将文件描述符从epoll中删除)

      fd----要操作的文件描述符

      event:

            struct epoll_event {

    __uint32_t   events;    /*感兴趣的事件*/

    epoll_data_t data;        /*私有数据*/

    };

    typedef union epoll_data {

    void        *ptr;

    int          fd;

    __uint32_t   u32;

    __uint64_t   u64;

    } epoll_data_t;

     返回值:0----成功    -1-----失败

     int epoll_wait(int epfd,

                    struct epoll_event *events,

    int maxevents,

    int timeout);

    功能:监听文件描述符,并带回活跃的文件描述符

    参数:epfd----epoll文件描述符

          events------出参,带回多个活跃的文件描述符的数组

      maxevents---最多可以带回多少个活跃的文件描述符

      timeout-----超时时间

    返回值:活跃的文件描述符的个数    -1---失败   0----超时

    K: 处理“addr already in use”问题:

           setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));

    L: UDP的函数:

    l1: int socket(AF_INET, SOCK_DGRAM, int 0);

    l2: ssize_t sendto(int sockfd,

                        const void *buf,

    size_t len,

    int flags,

                        const struct sockaddr *dest_addr,

    socklen_t addrlen);

    功能:发送udp数据

    参数:sockfd----套接字

          buf------发送数据

      len-----数据的长度

      flags-----0--->默认属性

      dest_addr:目的端的ip地址和端口号

      addrlen:地址结构体长度

     返回值:发送的字节数   -1---失败

    l3:  ssize_t recvfrom(int sockfd,

                           void *buf,  

       size_t len,

       int flags,

                           struct sockaddr *src_addr,

       socklen_t *addrlen);

     功能:接收数据

     参数:sockfd----套接字

           buf----接收数据的缓冲区

       len----缓冲区的长度

       flags----0-->默认属性

       src_addr----出参,带回发送端的ip地址和端口号

       addrlen:地址结构体的长度

      返回值:收到的信息   -1---失败

    注意:

         udp中只要调用recvfrom,就必须设置源端口号(bind)

    M: udp广播:

          打开广播功能:

          setsockopt(sockfd,

                 SOL_SOCKET,

                 SO_BROADCAST,

                 &on,

                 sizeof(int));      192.168.2.255

    N: 组播(多播):

          组播ip地址:224.0.0.0~239.255.255.255

      特殊的组播地址:

          224.0.0.1:所有具有组播功能的节点(主机   路由器)

      224.0.0.2:所有具有组播功能的路由器

      支持组播功能的命令:

          route add -net 224.0.0.0 netmask 240.0.0.0 dev em1(em1---连接网卡的名称)

      将本机IP地址添加到组播地址中:

          setsockopt(sockfd,

                 IPPROTO_IP,

     IP_ADD_MEMBERSHIP,

     &mreq,

     sizeof(struct ip_mreq));

      struct ip_mreq

      {

           struct in_addr imr_multiaddr;   //组播地址

    struct in_addr imr_interface;   //本机地址

      };

    O: 关闭防火墙:

          # service iptables stop   //临时关闭防火墙

      #chkconfig iptables off

      #vim /etc/selinux/config 修改SELINUX = disabled

    P: 登录:

           char *getpass(const chat *prompt);

           功能:接收密码

           参数:prompt-----提示信息

           返回值:接收的密码

       struct spwd *getspnam(const char *name);

            功能:根据用户名name返回/etc/shadow文件的内容

           char *crypt(const char *key, const char *salt);

            功能:将key加密

    参数:key----明码

          salt-----参照

    返回值:加密后的密码

    Q: ftp功能:

        1.登录(服务器端的系统用户名称和密码)

    2.pwd:显示服务器端当前的操作目录

           用户登录成功后的路径:登录用户的家目录

    3.cd:切换命令的名称(../..)

          cd命令的结果:250 Directory successfully changed.

                    550 Failed to change directory.

    4.ls:浏览服务器端的当前目录下的内容

          ls命令的结果:文件类型、文件权限、硬链接数、用户id、用户组的id、大小、时间、文件名称

    5.get:从服务器端下载文件,下载的文件存放到当前登录服务器的目录下

    6.put:将客户端的文件上传到服务器端上,存放上传文件的目录是当前服务器的目录

        7.quit:客户端结束运行

      

      客户端功能:

          接收命令和参数,将命令和参数发送给服务器,并等待命令的结果

    命令:enum ftp_cmd

          {

       CMD_LOGIN,

    CMD_PWD,

    CMD_CD,

    CMD_LS,

    CMD_PUT,

    CMD_GET,

    CMD_QUIT,

    CMD_MAX

      };

     struct arg_login

     {

      char login_user[512];

    char login_pwd[512];

     };

              struct cli_to_ser

      {

       int ftp_cmd;   //命令

    union

    {

    struct arg_login argLogin;

    char argCd[1024];

    char argGet[1024];

    char argPut[1024];

    }ftp_arg;

      };

    等待结果:struct ser_to_cli

      {

       int result;   //0---登录成功   -1----失败   -2---Failed to change directory.      1----Directory successfully changed.   2---ls命令完毕   3--get/put失败

               char string_result[512];

      };

      服务器功能:1.接收进程-----负责接收数据

                  |    struct recv_to_opt

      |    {

       (无名管道) |   struct cli_to_ser data;

      | struct sockaddr_in cli_addr;

      |   };

                  2.处理进程-----负责查看客户端是否以前登录过服务器,如果没有登录服务器,则记录客户端的登录信息,并创建子进程为客户端服务。如果登录过服务器,直接将数据封装完毕后发送给客户端对应的子进程。

      |

      | (每个子进程---处理进程:创建一个众所周知的管道)          

      |  或者

      |  (消息队列)

      |

      3.子进程集----负责处理命令,并将处理结果发送给对应的客户端

    注意:

        1.文件传输时使用tcp,客户端是被动端,服务器端子进程是主动端

    2.当服务器端子进程接收到quit命令时,子进程将登录表中的客户端对应的信息删除,子进程向客户端发送quit命令执行成功,子进程消亡,该子进程的父进程一定为其收尸,避免僵尸进程。

      客户端登录表(临界资源,在共享内存---互斥(信号量)中开辟空间,以数组的方式存储):

         struct cli_login_table

     {

      struct in_addr cli_addr;

    pid_t child_pid;

     };

          

    R: ipv6:

        1.查看是否有ipv6模块

            lsmod | grep ipv6   

    2.开启ipv6功能:

        vim /etc/sysconfig/network--------》NETWORKING_IPV6=yes

    3.ipv6的地址:

        ipv4的地址长度是32b(4个bytes)

    ipv6的地址长度是128b(16个bytes)

         fe80::d6be:d9ff:fed4:90be/64-----64区分网络段和主机段,所以ipv6没有子网掩码

    4.特殊的ipv6地址:

         0:0:0:0:0:0:0:0------>INADDR_ANY

     ::1--------->127.0.0.1

    5.临时设置ipv6地址

         ifconfig em1 add ipv6地址

      长久设置:

         vim /etc/sysconfig/network-scripts/ifcfg-em1---------》IPV6INIT=yes   IPV6ADDR=IPV6地址

    6.ipv6地址结构体

         struct sockaddr_in6

     {

      sin6_family;

    sin6_port;

    sin6_addr;

     };

    S: unix域套接字(不是协议):

           应用于:进程间通信

       协议族:AF_LOCAL

       地址结构体:struct sockaddr_un

           {

    short sun_family;   //AF_LOCAL--tcp   AF_UNIX---udp

    char sun_path[];   //地址就是一个文件

       };

    计算地址结构体的长度:SUN_LEN(&address);

    T: 设置tags文件:

      1.进入要设置tags的目录

      2.生成tags文件:ctags -R

      3.把tags文件添加到vim中:vim /etc/vimrc 加入 set tags=/usr/include/tags

  • 相关阅读:
    Hash索引和B树索引
    同步,异步,阻塞,非阻塞
    程序指令的异常跳转setjmp, longjmp和异常
    detangle c++ symbols
    RAID-4与模2和
    return, exit, _exit的区别
    metaprogramming笔记
    C++中的数组与指针
    LeetCode-3. Longest Substring Without Repeating Characters
    LeetCode-1. Two Sum
  • 原文地址:https://www.cnblogs.com/jfyl1573/p/6250077.html
Copyright © 2011-2022 走看看