Linux 嵌入式开发学习 网络编程day5:(包含前四天整理)。

    
【问题汇总】
1、服务器和客户端的  函数参数 返回值 不太理解
    TCP  UDP
    tcp
    服务器端:
         1. socket();功能是创建文件描述符,用于连接sockfd;
            参数: a. AF_INET    IPv4
                  b. 协议类型
                   SOCK_STREAM  TCP
                  SOCK_DGRAM   UDP
                  SOCK_RAW     原始套接字
                   3. 0
                    系统默认自动帮助匹配对应协议
                    传输层:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
                    网络层:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)    
             返回  错误 < 0
                     > 0 返回的文件描述符
用法:
                 
         2. bind(); 绑定,将IP 端口号 协议 和sockfd进行绑定;
 绑定之前填充结构体:        
用法:
                    参数: sockfd
                   struct sockaddr  通用结构体  16字节
                   struct sockaddr_in clientaddr;
                   struct sockaddr_un
                   
                   (struct sockaddr *)&clientaddr;
                   
         3. listen();用于监听,将主动套接字变为被动套接字;
            sockfd
            客户端同时连接服务器最大个数,   连接队列
            成功返回0
            出错返回-1
            用法:
 
            
        4. accept(); 阻塞等待客户端的连接,当有客户连接上来, accept()返回,并且声称一个文件描述符acceptfd, acceptfd用于通信;
            参数:
                sockfd
                第二个和第三个参数如果传NULL,
                    表示服务器不关心具体是哪一个客户端连接的;
                如果需要关心是哪个客户端,则需要传入第二和第三个参数
                (struct sockaddr *)&clientaddr     
            用法示例:
                    
         5. recv();接收数据
            recv(acceptfd,buf,sizeof(buf),0) //阻塞
            recv(acceptfd,buf,sizeof(buf),MSG_DONTWAIT) //非阻塞
            返回值:
                < 0 错误;
                ==0 客户端退出,断开连接
                > 0 成功接收到的字节个数
            用法示例:
        
         6. send();
             send(acceptfd,buf,sizeof(buf),0)
            返回值:    
                >0 成功发送的字节个数
                -1 失败
            用法示例:
    
    客户端:
        1. socket(); 功能是创建文件描述符,用于连接sockfd;
        2. connect(); 用于连接的;
            connect(sockfd, (struct sockaddr *)&serveraddr,addrlen);
            
        3. send;
        4. recv;
        
        
    UDP:
    服务器端:
        1. socket();
            填充结构体
        2. bind();
        3. recvfrom();
        4. sendto();send
        
    客户端:
        1. socket()
            填充结构体
        2. sendto()
        3. recvfrom();
    
2、多进程、多线程并发程序理解不太好
    并发服务器
        多进程  fork()
        多线程            
        IO多路复用
        思想:
            1. 创建一个关于文件描述符的表(集合)
            2. 将关心的文件描述符加入到集合当中
            3. 调用函数
                select poll 轮询机制
            4. 循环判断是哪个文件描述符产生事件
            (select返回之后会将除了自生那一位全部清0)
            5. 做对应的操作
            
            poll   轮询, 数据拷贝
            int poll(struct pollfd *fds, nfds_t nfds, int timeout);
            epoll
                参考代码 和 day4笔记
            
3、IO 多路复用的用法,以及各个参数及select 监听多个文件描述符的参数
4、epoll操作步骤和流程
6、unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -sizeof(unsigned short int) - sizeof(struct in_addr)];这一段是啥意思。
7、UDP聊天室如何让服务器对多个客户端发送数据
    链表,
    
8、三次握手,四次挥手
【1】网络属性设置
    getsockopt setsockopt
    int setsockopt(int sockfd,int level,int optname,
            const void *optval,socklen_t optlen)
            
    功能: 设置套接字属性
    参数:
        sockfd
        
        level指定控制套接字的层次.
        可以取三种值:
        1)SOL_SOCKET: 应用层
        2)IPPROTO_IP: 网络层  
        3)IPPROTO_TCP:传输层
        
        optname:
            SO_REUSEADDR 允许重用本地地址和端口
    
        optval
            int val = 1;
            &val
        optlen
            大小
            
    如果想解决地址端口号重用的问题:
        setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
    前提是:
             1. 得先创建sockfd,
            2. 在bind函数之前调用setsockopt();
    
    
    int getsockopt(int sockfd,int level,int optname,
            void *optval,socklen_t  *optlen);
    功能: 获取套接字得属性
    想获取sockfd套接字得接收缓冲区大小:
    
    int optval;
    socklen_t  optlen = sizeo(optval);
    getsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&optval,&optlen);
    
    printf("recvbuf = %d\n",optval);
        
【2】网络超时检测
    1. select/poll中都有设置
    select(maxfd + 1,&readfd,NULL,NULL, NULL);//没有超时检测的,NULL
    
    select(maxfd + 1,&readfd,NULL,NULL, &tv);
    
            
            定义超时检测变量tv:
                struct timeval tv = {1,0}; //1秒
    
                struct timeval tv = {
                    .tv_sec = 1,
                    .tv_usec = 0,
                };
    
    如果select没有设置超时时间:
        它的返回值有两种:
                 < 0  错误
                 > 0  表示有一个或多个事件产生
    
    如果select设置了超时时间:
                < 0 出错
                > 0 表示有一个或多个事件产生
                == 0 表示超时
示例:
===============================================
     poll函数设置超时时间
        
     int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    poll函数第三个参数是设置超时时间
        如果 -1  阻塞
        其他 1000  (毫秒级别)
    
================================================    
     2. 通过setsockopt来设置超时时间 
        SO_RCVTIMEO      接收超时
        
        struct timeval tv = {1,0};
        服务器端通过设置acceptfd属性,来设置超时时间
         setsockopt(acceptfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));
        
用法:放到while循环里的accept函数后面
  
   3. alarm(5) 闹钟   定时器
        5秒之后会,会有一个信号产生(SGIALRM)
        alarm会打断下一个系统调用
    
        #include <signal.h>
        int sigaction(int signum, const struct sigaction *act,  struct sigaction *oldact);
        
            signum  信号        
         struct sigaction {
               void     (*sa_handler)(int);
           };
        ========================================
        void handler()
        {
            printf("timeout .....\n");
        }   
        
        struct sigaction act;
        sigaction(SIGALRM,NULL,&act);  //1. 获取属性
        act.sa_handler = handler;          //2. 修改
        sigaction(SIGALRM,&act,NULL);  //3. 写回  
        
        在recv前调用alarm函数
        alarm的 SIGALRM信号产生后会打断(终端)下面的系统调用recv;
    代码中的用法示例:
        ========================================
    
【3】广播和组播
     广播  (UDP协议)
    (1)以192.168.1.0(255.255.255.0)网段为例,最大的主机地址192.168.1.255  IP是广播地址
    (2)255.255.255.255在所有的网段中都是广播地址
广播代码流程:
广播的发送者:tcp client.c
    1. 创建用户数据报套接字;
         sockfd = socket(AF_INET,SOCK_DGRAM,0);
    2. 缺省创建的套接字默认是 不允许广播数据包发送的,需要设置属性
         setsockopt可以设置套接字属性
     int optval = 1;
     setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&optval,sizeo(optval));
    3. 接收方地址指定为广播地址,指定端口号
         struct sockaddr_in recvaddr;
        ...
    4. 发送数据包
         sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&recvaddr,xxx);
    
    
广播的接收者:类似:tcp server.c
    1. 创建用户数据报套接字
         sockfd = socket(AF_INET,SOCK_DGRAM,0);
    2.
        绑定IP地址(广播IP或0.0.0.0)和端口
        绑定的端口必须和发送方指定的端口相同
         struct sockaddr_in recvaddr,sendaddr;
 
         bind(sockfd,(struct sockaddr *)&recvaddr,xxx);
    3. 等待接收数据
         recvfrom();
【4】组播
组播代码流程:
组播的发送者:
    1. 创建用户数据报套接字
    2. 指定接收方地址指定为组播地址 224.0.0.10
        指定端口信息
    3. 发送数据包
组播的接收者:
    1. 创建用户数据报套接字
    2. 加入多播组
        struct ip_mreq  {
            struct in_addr imr_multiaddr;  // 组播IP 224.0.0.10
            struct in_addr imr_interface;  // INA DDR_ANY    
        };
        
         struct ip_mreq mreq;
        mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.10");
        mreq.imr_interface.s_addr = htons(INADDR_ANY);
     setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
        
    3.
        绑定IP地址(加入组的组播IP或0.0.0.0)和端口
        绑定的端口必须和发送方指定的端口相同
        
    4. 等待接收数据
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值