zoukankan      html  css  js  c++  java
  • C语言安利一波函数封装

       最近学弟学妹们在写聊天室,期间遇到了很多问题,也“逼迫”我们这些大二(其实即将大三)狗考虑了许多以前没有考虑过的东西。现在就着我们小组的聊天室的项目,送给学弟学妹们”几个可能安全的封装函数。“

    frist : 保证发送“len”字节到套接字

    ssize_t Sendlen(int fd, const void *buf, size_t len, int flags)
    {
        ssize_t n = 0;
        size_t sum = 0;
        const char *ptr;
        ptr = (const char *)buf;
        while (sum < len)
        {
            n = send(fd, (void *)ptr, len - sum, flags);
            if (n < 0)
            {
                if (errno == EINTR)
                    n = 0;
                else
                    err_sys("send error ", __LINE__);
            }
            sum += n;
            ptr += n;
        }
        return (sum);
    }

    second:保证接受“len”字节到套接字

    ssize_t Recvlen(int fd, void *buf, size_t len, int flags) 
    {
        ssize_t n = 0;
        size_t sum = 0;
        const char *ptr;
        ptr = buf;
        while (sum < len)
        {
            n = recv(fd, (void *)ptr, len - sum, flags);
            if (n < 0)
            {
                if (errno == EINTR)
                    n = 0;
                else
                    err_sys("recv error ", __LINE__);
            }
            else if (n == 0)
            {
                printf("对端连接关闭!!!
    ");
                break;
            }
            sum += n;
            ptr += n;
        }
        return (sum);
    }

    thrid:从套接字读取一行数据

    static int recv_cnt = 0;
    static char *recv_ptr = NULL;
    static char recv_buf[MAXLINE];
    
    static ssize_t my_recv(int fd, char *ptr, int flags)
    {
        if (recv_cnt <= 0)
        {
        again:
            if ((recv_cnt = recv(fd, recv_buf, sizeof(recv_buf), flags)) < 0)
            {
                if (errno == EINTR)
                    goto again;
                else
                    return (-1);
            }
            else if (recv_cnt == 0)
            {
                return (0);
            }
            recv_ptr = recv_buf;
        }
        recv_cnt--;
        *ptr = *recv_ptr++;
        return (1);
    }
    ssize_t recvline(int fd, void *vptr, size_t maxlen, int flags)
    {
        ssize_t n, rc;
        char c, *ptr;
        ptr = vptr;
        for (n = 1; n < maxlen; n++)
        {
            if ((rc = my_recv(fd, &c, flags)) == 1)
            {
                *ptr++ = c;
                if (c == '
    ')
                    break;
            }
            else if (rc == 0)
            {
                *ptr = 0;
                return (n - 1);
            }
            else
                return (-1);
        }
        *ptr = 0;
        return (n);
    }
    ssize_t Recvline(int fd, void *buf, size_t Maxlen, int flags)
    { //注意参数 Maxlen
        ssize_t n;
        if ((n = recvline(fd, buf, Maxlen, flags)) < 0)
            err_sys("recvline error ", __LINE__);
        return (n);
    }

    注意事项:

    send和recv有三个要点:

    1. 在每次进行send或者recv时,第二个参数是随着读取的字节数量而改变的。

    2. 传进来的第二个参数是 void *的类型,给他加1减1,就会出现问题。必须首先转换为char *

    3. 第三个参数len。同上,也是需要随着读取的字节数而改变

    recvline

    static int recv_cnt = 0; //读取的数据量
    static char *recv_ptr = NULL; //指向recv_buf的字节型指针
    static char recv_buf[MAXLINE]; //存放读取数据的结构
    

    recvline 函数从recv_buf中拿到一行数据 。
    my_recv函数检查如果读取的数据量 <=0,就进行一次读取。问:这里为什么要用recv而不用自己封装的 Recvlen? 因为Recvlen直到读取len个字节才会返回,而我们这里并不要求,只要读取从缓冲区中读取比MAXLINE小的字节就行了 。

    if (recv_cnt <= 0)
        {
    again:
            if ((recv_cnt = recv(fd, recv_buf, sizeof(recv_buf), flags)) < 0)
            {
                if (errno == EINTR)
                    goto again;
                else
                    return (-1);
            }
            else if (recv_cnt == 0)
            {
                return (0);
            }
            recv_ptr = recv_buf;
        }

    bug:考虑到多线程,多进程,在循环send或者recv时应该加上锁,不然万一有两个线程往同一个套接字发送数据,而时间片又进行了转换了,就会造成错乱,保证不了完整的发送一个结构体数据了。

  • 相关阅读:
    第七周总结
    第六周总结
    第五周总结
    第四周总结
    第三周总结
    第二周总结
    第一周总结
    《需求分析和系统设计》阅读笔记三
    《需求分析和系统设计》阅读笔记二
    Linux——error while loading shared libraries 的解决方法
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335260.html
Copyright © 2011-2022 走看看