基于UDP/TCP网络套接字编程

 套接字网络编程 :


        IP地址:唯一标识网络上的一台主机
             IPV4:uint32_t ---为了便于记忆,以点分十进制字符串形式展示
             IPV6:uchar addr[16]---不向下兼容IPV4---没有发展起来
             saddr(源IP地址)--> daddr(目的IP地址)    从哪个主机发送到指定主机
         PORT端口:标识一台主机上的进程
             uint16_t ---端口的返回:0-65535  其中0-1024不推荐使用
             特性: 一个端口只能被一个进程使用    一个进程可以使用多个端口
             sport(源端口)—>  dport(目的端口)     从哪个进程发送到指定进程
             saddr sport  daddr dport proto(协议) ---五元组--标识一条通信
           网络字节序:
              字节序:cpu对数据在内存中存取的顺序
                  大端字节序:高地址存低位
                  小端字节序:低地址存地位
              计算机的字节序取决于cpu架构:
                   X86_64----小端字节序
                   MIPS------大端字节序    
              字节序检测:联合体    
                           
              因为在网络通信中,通信双方因为主机字节序不同,而导致数据二义性,
         因此就指定标准:在网络上通信,通信双方都必须使用网络字节序--大端字节序
         
         通信的时候总是分客户端和服务端
              客户端是主动请求的一方,服务端是被动的一方
              但是服务端要告诉客户端自己的IP+PORT ,客户端才能将请求发送过来
         用户层协议自己定,但是传输层有两个协议,用哪一个更好?
              tcp:传输控制协议:面向连接,可靠传输,面向字节流->提供字节流服务
                  数据安全性要求较高的程序,文件传输
              udp:用户数据报协议:无连接,不可靠,面向数据报
                  数据安全性没那么高,传输速度快适用于实时性要求高的程序->视频,音乐传输
              因为tcp为了实现安全传输,牺牲了部分性能,因此虽然安全性相较于udp较低

传输层基于udp的网络通信流程:
           客户端                                    服务端
       1.创建套接字---返回套接字句柄   socket        1.创建套接字---返回套接字句柄
       2.为套接字绑定地址和端口           bind            2.为套接字绑定地址和端口
       
       3.发送数据                                       sendto       3.开始接收数据
       4.接收数据                                       recvfrom    4.恢复数据

       5.关闭套接字                                    close         5.关闭套接字
     
     客户端我们不建议手动绑定地址,因为如果端口冲突,客户端就会启动失败,但是
     客户端对端口并没有硬规定;客户端发送数据,操作系统检测到还没绑定地址,则
     会选择合适的地址进行绑定
     
         //1.创建套接字     
         int socket(int domain,int type, int protocol);
         //domain:  地址域
         //   AF_INET   表示使用IPV4协议
         // type: 套接字类型
         //      SOCK_STREAM 流式套接字--默认协议TCP
         //      SOCK_DGRAM  数据报套接字--默认协议UDP
         // protocol:
         //    0    使用默认协议
         //   IPPROTO_TCP  6   TCP协议
         //   IPPROTO_UDP  17  UDP协议         
         //返回值: 套接字操作句柄-文件描述符   失败:-1
         
         //2.为套接字绑定地址信息
         //因为网络通信使用网络字节序,因此端口和ip地址信息都需要被转换
         //成网络字节序的数据
         //uint16_t htons(uint16_t hostshort);
         //将十六位色数据从主机字节序转换为网络字节序
         //uint32_t htonl(uint32_t hostshort)
         //将32位的数据从主机字节序转换成网络字节序


         //int_addr_t inet_addr(const char* cp)
         //将字符串点分十进制IP地址转换位网络字节序的整数IP地址
         
         //bind(int sockfd,struct sockadd* addr,sock_len addrlen);
         //sockfd:创建套接字返回的套接字描述符
         //addr:要绑定的地址信息
         //addrlen:地址信息长度
         //返回值: 0     失败:-1
         
         bool Recv(std::string& buf,sockaddr_in* _addr=NULL)//接收数据
         //ssize_t recvfrom(int sockfd,void* buf,size_t len,
         //int flags,struct sockaddr* src_addr,socklen_t* addrlen);
         //sockfd:套接字描述符
         //bf:    用于保存接收铺的数据
         //len:   要接收数据的长度
         //flags: 默认0--阻塞接收--没有数据则阻塞
         //src_addr: 发送端的地址信息
         //addrlen:  输入输出型参数,用于获取地址信息的长度
         //返回值:实际接收的数据长度    失败:-1
         
          bool Send(std::string &buf, struct sockaddr_in &addr)//发送数据
          //ssize_t sendto(int sockfd, const void *buf, size_t len, 
          //int flags,struct sockaddr *dest_addr, socklen_t addrlen);
          //  dest_addr:  目的端地址信息
          //  addrlen:    地址信息长度
 
         ./udp_srv  0.0.0.0 6666    //0.0.0.0  监控当前主机所有发送到6666端口的信息
         netstat -anptu     //查看网络状态
         服务端监听了什么地址,客户端发送数据的时候目的端地址就必须是多少
         (云服务器需要注意,服务端监听应该是内网地址,但是客户端要访问公网地址)
         服务端监听0.0.0.0地址表示监听当前计算机上所有网卡
         (需要注意客户端不能使用0.0.0.0地址)
         
         mysql 端口:3306  8080
         
         
         
     基于TCP协议的网络通信客户端服务端程序编写
              客户端                           服务端
         1.创建套接字                        1.创建套接字 
         2.不推荐绑定地址信息              2.绑定地址信息
          
         3.向服务端发起连接请求             3.开始监听
                                               int listen(int socket,int backlog)
                                               告诉操作系统可以接收连接请求
                                               建立连接的过程由操作系统完成
                                               backlog:同一时间的客户端最大并发连接数
                                               客户端一旦建立成功,服务端会单独创建一个socket
                                               专门与指定客户进行通信
                                              4.阻塞接收已完成连接客户端信息
                                                  newfd=accept(sockfd,srd_addr,len)
                                                 从已完成连接队列中取出一个socket
        4.收发数据                              5.使用这个针对客户端与新建的socket与客户端进行通信
                                                  Recv(newfd,)
                                                  Send()
        5.关闭套接字                          6.关闭套接字
        
       tcp在操作系统会进行保活检测,如果连续好几次保活检测失败,则认为连接断开
         sysctl  -a|grep keep     tcp具有自己的保活探测机制
       在代码中,若断开连接/或对端关闭连接-->recv返回0;
                                              send 会触发异常--SIGPIPE-导致进程退出        
       基本的tcp服务端程序只能同时只能与一个客户端进行通信:因为服务端不知道    
       客户端数据什么时候到来,因此服务端的程序流程只能写死,而写死可能导致
       阻塞(accept/recv)    accept阻塞:新的客户端一直没来,就会阻塞
                            recv阻塞:客户端没有发数据就会一直阻塞

       多进程tcp服务程序:一个子进程处理一个客户端,实现多个客户端同时处理
              父进程必须关闭客户端socket
                      
        多线程tcp服务程序:一个子线程处理一个客户端,实现多个客户端同时处理
              主线程不能关闭socket;同时一个进程中的线程共享文件描述符表;    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值