linux socket 函数封装

来源:互联网 发布:淘宝卖家加入花呗条件 编辑:程序博客网 时间:2024/04/30 10:24

1、linux socket函数介绍

最近一直在看《unix网络编程》,有感于书中例子给出的创建tcp连接时对socket函数的封装。对于在服务器端编写网络程序的人来说,将这些函数进行封装能大大提高编程效率,而且还能简化编程流程,提高代码可复用性。

2、socket函数封装

首先,介绍一下socket函数用到的基本结构变量:
struct sockaddr_in server;       server.sin_family = AF_INET;       //簇server.sin_port = htons(PORT);     //端口server.sin_addr.s_addr = htons(INADDR_ANY);  //ip地址

下面依次对各函数进行封装,针对创建TCP连接:

2.1、socket()

int Socket(int domain, int type){        int sockfd = 0;        sockfd = socket(domain, type, 0);        if (sockfd < 0)         {                 return -1;         }                   return sockfd;}

在创建socket成功后,一般要对套接口设定一些选项,这儿根据实际情况自行设定。

2.2、bind()

int Bind(int sockfd, const struct sockaddr *net_addr, socklen_t addrlen){    if (!net_addr)    {           printf("when binding, net_addr is NULL\n");        return -1;     }       if (bind(sockfd, net_addr, len) < 0)    {           printf("fail to bind ipaddr\n");        return -1;     }       return 0;}

2.3、listen()

int Listen(int sockfd, int listenNum){    if (listen(sockfd, listenNum) < 0)    {        printf("fail to listen socket\n");        return -1;    }    return 0;}

在这步之后,我们绝大多时候会将套接口设为非阻塞性套接口,这样在监听套接口时,不用阻塞性监听,设置非阻塞性套接口如下:
int setNonBlock(int sockfd){    int opt = 0;    opt = fcntl(sockfd, F_GETFL);    if(opt < 0)    {        printf(  "fcntl(sock,GETFL) failed");        return -1;    }    opt = opt|O_NONBLOCK;    if(fcntl(sockfd, F_SETFL, opt) < 0)    {        printf(  "fcntl(sock,SETFL,opts) failed");        return -1;    }           return 0;}

当然最重要是如下两个函数了:

2.4、read()

int Read(int fd, void *sp, size_t size_len){    int readlen = 0;    int rn = 0;    while (readlen < size_len)    {        rn = read(fd, sp + readlen, size_len - readlen);        if (rn < 0)        {            if (errno == EAGAIN || errno == EINTR)   //如果设置了非阻塞,返回errno 为EAGAIN,继续读;如果遇到中断也继续读            {                continue;            }            else            {                return -1;            }        }        else if (rn < size_len)        {            if (rn == 0)            {                //no data                return readlen;            }            readlen += rn;        }        else        {            readlen = rn;        }    }    return readlen;}

2.5、write()

int Write(int fd, void *sp, size_t size_len){    int sendlen = 0;    int sn = 0;    while (sendlen < size_len)    {        sn = write(fd, sp + sendlen, size_len - sendlen);        if (sn < 0)        {            if (errno == EAGAIN || errno == EINTR)   //如果设置了非阻塞,返回errno 为EAGAIN,继续写;如果遇到中断也继续写            {                continue;            }            else            {                return -1;            }        }        else if (sn < size_len)        {            sendlen += sn;        }        else        {            sendlen = sn;        }    }    return sendlen;}

这就是在学习中,对socket常用的函数的封装,记录下来供自己后序学习,在read和write函数中,还应该有一个重要的考虑,我们常常在write或者read的时候,或许由于对方数据并没有及时发送,造成一直循环读或者写,所以可以加一个超时判断机制,当在多长时间内读写还没完成时,返回错误,以免造成不必要的效率的浪费。


原创粉丝点击