• 第44天-基于Tcp的网络程序(2013.09.18)


      1.IPv4和IPv6的地址格式定义在netinet/in.h中,

           IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位IP地址,

           IPv6地址用sockaddr_in6结构体表示, 包括16位端口,128位IP地址和一些控制字段。

      2.Socket的地址格式定义在sys/un.h中,用sockaddr_un结构体表示。各种sockket地址结构体的开头都是相同的,前16位表示整个结构体的长度,后16位表示地址类型。

      3.IPv4  地址类型  AF_INET

        IPv6   地址类型  AF_INET6

        Unix Domain Socket  地址类型 AF_UNIX

        所以只要取得某种Socket结构体的首地址,就可以根据地址类型确定结构体的内容

      4.sockaddr_in中的成员struct in_addr  表示32位的IP地址, 我们通常用点分十进制的字符串表示IP地址

        字符串转in_addr的函数

          函数原型 :#include <arpa/inet.h>

            int inet_aron(const cchar *strptr, struct in_addr *addrptr);

            in_addr_t inet_addr(const char *strptr);

            int inet_pton(int family, const char *strptr, void *addrptr);

        in_addr转字符串函数

            char *inet_ntoa(struct in_addr inaddr);

            const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

      5.TCP 协议的客户端、服务器程序的一般流程

      6.流程简介

      7.程序中用到的socket API, 这些函数都在sys/socket.h中

        int socket(int family, int type, int protool);

            作用 : socket打开一个网络通讯端口,成功返回一个文件描述符, ,失败返回-1.

                  对于IPv4,family参数指定为AF_INET,

                  对于Tcp协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。

                  如果是UDP协议, 则type参数指定为SOCK_DGRAM, 表示面向数据报的传输协议。

                  protool参数的介绍从略,指定为0即可

        int bind(int scokfd, const struct sockaddr *myaddr, socklen_t addrlen);

            作用 : 客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号

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

        对于myaddr参数的初始化

              bzero(&servaddr, sizeof(servaddr));    //结构体清零

              servaddr.sin_family = AF_INET;      //设置地址类型

              servaddr.sin_addr.s_addr = htol(INADDR_ANY);  //设置为任意IP地址

              servaddr.sin_port = htons(SERV_PROT);    //端口号

        int listen(int sockfd, int backlog);

            作用 : listen()声明sockfd处于监听状态, 并且最多允许有backlog个客户端处于连接状态,如果接受到更多的连接请求就忽略。

            返回值 ; 成功返回0, 失败返回-1

        int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

            流程 : 在三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还么有客户端的连接请求,就阻塞等待直到有客户端连接上来

            cliaddr是一个传出参数 : accept()返回时传出的客户端的地址和端口号

            addrlen是一个传入传出参数 : 传入的是调用者提供的缓冲区cliaddr的长度以避免缓冲区溢出的问题。传出的是客户端地址结构体的实际长度(有可能么有占满调用者提供的缓冲区)如果给cliaddr参数传NULL, 表示不关心客户端的地址

        int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

            客户端需要调用connect()连接服务器。

            connect 和 bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址

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

      8.错误处理和读写控制

          慢系统调用accept, read和write被信号中断时应该重试

          connect虽然也会阻塞,但是被信号中断时不能立刻重试。对于accept, 如果errno是ECONNABORTED, 重试。

        传入传出参数(value-result argument)

  • 相关阅读:
    简单的描述Java中的构造函数,及访问修饰符
    MyEclipse中常用的快捷键大全,快来.....
    转:攻击JavaWeb应用[1]-javaEE基础
    转:vscode中调试php
    转:java-Servlet开发
    转:Spring学习笔记---Spring Security登录页
    实战栈溢出:三个漏洞搞定一台路由器(转自长亭科技)
    gdbserver静态编译
    gdb调试若干问题
    转:Apache+Fastcgi+Django
  • 原文地址:https://www.cnblogs.com/cxw825873709/p/3330371.html
Copyright © 2020-2023  润新知