网络编程基础介绍

一、OSI七层结构
    应用层(http,FTP)
    表示层(文件、数据加密)
    会话层(会话管理)
    传输层(tcp协议)
    网络层(IP协议)
    数据链路层(IP地址转到物理地址)
    物理层(以太网)
二、tcp/ip协议
    (1)常用协议
        tcp、udp、ip
    (2)ip地址
        标识主机(ip地址头包含两个内容:源地址IP、目标地址IP)
        IP地址的点分十进制形式:xxx.xxx.xxx.xxx(点代表一个字节的结束,一共四字节,32位)
        A类:第一个字节以0开头(即第一个字节的第一位为0),范围: 1.0.0.0 ~ 126.255.255.255     
              0.0.0.0可代表任意IP,所以用户不能私用;
              127.0.0.0 ~ 127.255.255.255属于本地测试地址,不能跨越主机;
              子网掩码:为了区分网络号与主机号
              A类地址的子网掩码一般为: 255.0.0.0
              A类地址第一个字节为网络号,后三个字节为主机号
              
        B类:第一个字节以10开头,范围: 128.0.0.0 ~ 191.255.255.255
             子网掩码一般为: 255.255.0.0
             前两个字节为网络号,后两个字节为主机号
             
        C类:第一个字节以110开头,范围: 192.0.0.0 ~ 223.255.255.255
             子网掩码一般为: 255.255.255.0
             前三个字节为网络号,最后一个字节代表主机号
             
        D类:第一个字节以1110开头,范围: 224.0.0.0 ~ 239.255.255.255
        E类: 第一个字节以11110开头 范围: 240.0.0.0 ~ 255.255.255.255
    (3)端口号
        标识进程(Linux系统通过端口号来决定哪一个进程来服务)
        众所周知端口: 1~1023(1~255之前为众所周知端口,255~1023端口通常由UNIX系统占用)
        已登记端口: 1024~49151  程序可以使用的端口
        动态或私有端口: 49152~65535
    (4)字节序
        主机字节序:如果是Intel的芯片,采用i386架构,字节序为小端序
                    小端序:低地址存放低字节。输出是倒过来输出
                    例如: int a =0x12345678;  存放的方式: 78、56、34、12
                            打印第一个字节的话是 78 打印两个字节是 5678
                    主机序转网络字节序:    htons(); htonl();
                    
        网络字节序:基本都是大端序
                    大端序:低地址存放高字节。
                    例如: int 0x12345678;  存放方式: 12 34 56 78
                            打印第一个字节的话是 12
                    网络字节序转主机序:    ntohs(); ntohl();
三、套接字
    (1)socket
        是一种编程接口
        是一种特殊的文件描述符
        并不仅限与TCP/IP协议
    (2)socket类型
        ①流式套接字(tcp编程)
        提供一个面向连接、可靠的数据传输服务,数据无误差、无重复的发送且按照发送顺序接收。
        内置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。
        ②数据报套接字(udp编程)
        提供无连接服务。数据包以独立数据包的形式发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。
        ③原始套接字
        可以对较低层次协议如ip、icmp直接访问。
    (3)tcp和udp协议
        共同点:属于传输层协议
        TCP:传输控制协议
            面向连接,保证可靠(流式套接字SOCK_STREAM)
        UDP :用户数据报协议
              无连接,不可靠  (数据报套接字SOCK_DGRAM)
四、tcp三次握手
    第一次握手:客户端发送SYN报文
        操作:客户端向服务器发送一个SYN(Synchronize Sequence Numbers,同步序列编号)报文,该报文不包含应用层数据,其首部的同步位SYN被置为1。
              报文中还包括客户端的初始序列号(ISN,Initial Sequence Number),用于后续的数据传输和确认。
        状态:发送SYN报文后,客户端进入SYN_SENT(同步已发送)状态,等待服务器的确认。
    第二次握手:服务器发送SYN/ACK报文
        操作:服务器收到客户端的SYN报文后,会以自己的SYN报文作为应答,同时指定自己的初始序列号。
              服务器还会在SYN报文中对客户端的初始序列号加1作为确认号(ACK,Acknowledgment),表示已经收到了客户端的SYN报文。
        状态:发送SYN/ACK报文后,服务器进入SYN_RCVD(同步收到)状态,等待客户端的确认。
    第三次握手:客户端发送ACK报文
        操作:客户端收到服务器的SYN/ACK报文后,会发送一个ACK报文作为响应。该ACK报文中的确认号是服务器初始序列号加1,表示已经收到了服务器的SYN报文。
              此时,客户端的ACK报文可以携带应用层数据。
        状态:发送ACK报文后,客户端进入ESTABLISHED(已建立连接)状态,表示连接已经成功建立。服务器收到客户端的ACK报文后,也进入ESTABLISHED状态,双方可以进行正常的数据传输。
五、TCP服务器的搭建流程
        /*
            头文件:        #include <sys/socket.h>
                            #include <netinet/in.h>
                            #include <netinet/ip.h>
        */
    1、 socket();//创建一个套接字(创建网络通信文件)
        头文件:    #include <sys/types.h>         
                    #include <sys/socket.h>
        函数原型:    int socket(int domain, int type, int protocol);
        参数:        domain :用来指示通信文件的适用范围
                        AF_UNIX, AF_LOCAL       Local communication              unix(7)
                        AF_INET                 IPv4 Internet protocols          ip(7)
                        AF_INET6                IPv6 Internet protocols          ipv6(7)
                    type :用来指示套接字文件的类型
                        SOCK_STREAM :流式套接字(数据是以字节流的方式进行传输)TCP通信;
                        SOCK_DGRAM  :数据报套接字(数据是以一个包的形式进行发送)UDP通信;
                        SOCK_RAW    :原始套接字
                    protocol :指示采用的协议,一般采用默认值0
        返回值:    成功返回套接字文件描述符;    
                    失败返回-1
                    
    2、    设置服务器的地址以及端口信息,需要用到系统提供的结构体 struct sockaddr_in;
                    struct sockaddr_in  //提供给编程用户使用
                    struct sockaddr_in {
                            sin_family_t sin_family;
                            sin_port_t sin_port;
                            struct in_addr sin_addr;
                    }
                    
                    struct in_addr {
                            uint32_t       s_addr;    
                    };
        通用结构体 struct sockaddr;  //内核使用该结构体来操作
                   struct sockaddr {
                            sa_family_t sa_family;
                            char        sa_data[14];
                    }
        (1)端口号实现主机字节序到网络字节序的转换
                #include <arpa/inet.h>
                uint16_t htons(uint16_t hostshort);
        (2)IP地址实现点分形式的IP到网络字节序的IP地址转换
                #include <sys/socket.h>
                #include <netinet/in.h>
                #include <arpa/inet.h>
                in_addr_t inet_addr(const char *cp);
                点分十进制--->32位二进制网络字节序: inet_addr("127.0.0.1"); inet_aton();
                32位二进制网络字节序--->点分十进制: inet_ntoa();
                        
    3、 bind();//绑定套接字
        头文件:    #include <sys/types.h>          
                    #include <sys/socket.h>
        函数原型:    int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        参数:        sockfd :用来指示所要设置的服务器的文件描述符;
                    addr :用来存储IP地址和端口号
                    addrlen :表示地址空间的大小
        返回值:    成功返回0
                    失败返回-1
    4、 listen();//监听套接字
        头文件:    #include <sys/types.h>        
                    #include <sys/socket.h>
        函数原型:    int listen(int sockfd, int backlog);
        参数:        sockfd :用来指示所要启动监听的服务器的文件描述符
                    backlog :用来指示服务器在某一个时间点所能处理连接数队列的大小
        返回值:    成功返回0
                    失败返回-1
    5、 accept();//接收客户端请求(服务器等待客户端的连接,并且与客户端建立连接)
        头文件:    #include <sys/types.h>        
                    #include <sys/socket.h>
        函数原型:    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        参数:        sockfd :用来指示所要监听客户端连接请求的服务器的文件描述符;
                    addr :用来存储IP地址和端口号
                        存储所连接的客户端的IP地址和端口号,如果不关心客户端的IP地址和端口号可以用NULL来填充参数
                    addrlen :指示的客户端的IP地址和端口号结构体空间的大小;不关心的话用NULL填充
        返回值:    成功返回客户端连接成功的通信套接字文件描述符,用于后续数据的接收和发送;
                    失败返回-1
    6、 close();//关闭套接字
    
    发送数据:send()或者write()
              send(connfd, buf, sizeof(buf), 0);//阻塞
        头文件:    #include <sys/socket.h>
                    #include <sys/types.h>
        函数原型:    ssize_t send(int socket, const void *buffer, size_t length, int flags);
        参数:        buffer : 发送缓冲区首地址
                    length : 发送的字节数
                    flags : 发送方式(通常为0)
        返回值:    成功返回实际发送的字节数
                    失败返回-1
    接收数据:recv()或者read()
              recv(connfd, buf, sizeof(buf), 0);
        头文件:    #include <sys/socket.h>
                    #include <sys/types.h>
        函数原型:    ssize_t recv(int socket, const void *buffer, size_t length, int flags);
        参数:        buffer : 缓冲区首地址
                    length : z最大可接收的字节数
                    flags : 接收方式(通常为0)
        返回值:    成功返回实际接收的字节数
                    失败返回-1
六、TCP客户端创建流程
    1、 socket();//创建一个套接字
    2、    设置服务器的地址以及端口信息  struct sockaddr_in
    3、 connect();//请求连接客户端(客户端向服务器发送连接请求,并建立连接)
        头文件:    #include <sys/types.h>          
                    #include <sys/socket.h>
        函数原型:    int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        参数:        sockfd :用来指示发出请求的客户端的文件描述符
                    addr :用来存储IP地址和端口号(服务器的IP地址和端口号)
                    addrlen :指示的服务器地址空间的大小
        返回值:    成功返回0
                    失败返回-1
    4、 close();//关闭套接字

七、UDP服务器的创建流程
    1、创建数据报套接字 socket();    SOCK_DGRAM
    2、设置地址以及端口信息 struct sockaddr_in;
        sin_family;
        sin_port;
        sin_addr.s_addr;
    3、绑定套接字 bind();
    4、接收数据 recvfrom();
        头文件:    #include <sys/types.h>
                    #include <sys/socket.h>
        函数原型:    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
        参数:        sockfd :创建的套接字,是socket的返回值
                    buf : 接收数据的缓存区首地址
                    len : 接收的数据长度
                    flags :默认设置为0,阻塞模式。
                    src_addr :客户端的地址信息结构体,recvfrom函数内部获取
                    addrlen :地址长度指针
        返回值:    成功返回接收的字节数
                    失败返回-1
       发送数据 sendto(); 
        头文件:    #include <sys/types.h>
                    #include <sys/socket.h>
        函数原型:    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
        参数:        sockfd :创建的套接字,是socket的返回值
                    buf : 缓存区首地址
                    len : 发送的数据长度
                    flags :默认设置为0,阻塞模式。
                    dest_addr :客户端的地址信息结构体,recvfrom函数内部获取
                    addrlen :地址长度
        返回值:    成功返回接收的字节数
                    失败返回-1
八、TCP与UDP服务器的区别
    1、 tcp创建一个流式套接字(SOCK_STREAM)  --- udp创建一个数据报套接字(SOCK_DGRAM)
    2、 设置地址信息,struct sockaddr_in      --- 一样
    3、 绑定套接字(bind());                ---一样
    4、 监听listen()                          ---无
    5、 接受客户端的请求accept()              ---无
                                              recvfrom();接受客户端数据,并且得到客户端的地址信息
    6、关闭套接字close()                      ---关闭套接字        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值