您的位置:首页 > 运维架构 > Linux

Linux多线程服务器端编程笔记一

2014-02-10 12:39 330 查看
最近在阅读陈硕先生的《Linux多线程服务器端编程》,学习了一些socket接口的新用法,在这里做一下笔记。

一步创建非阻塞socket

socket函数原型如下:

int socket(int domain, int type, int protocol);

自从Linux-2.6.27后,type参数除了可以传递诸如SOCK_STREAM、SOCK_DGRAM等标志外,还可以传递SOCK_NONBLOCK、SOCK_CLOEXEC。SOCK_NONBLOCK设置新创建的文件描述符为非阻塞;设置SOCK_CLOEXEC标志后,程序执行execl系列函数后,文件描述符将被关闭,不能再使用,但是执行fork调用后,文件描述符被子进程继承,在子进程中仍然可以使用。有了这两个标志后,可以使用socket一步创建非阻塞的socket,比如创建一个非阻塞的TCP
socket:

int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NOBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
if (sockfd < 0)
{
perror("socket error")
}


accept4一步得到非阻塞socket

accept4在accept的基础上增加了flag参数,可以用来传递SOCK_NONBLOCK和SOCK_CLOEXEC。这样就可以让accept4直接返回非阻塞的连接描述符。

int connfd = accept4(sockfd, (struct sockaddr *)&addr, &addrlen, SOCK_NOBLOCK | SOCK_CLOEXEC);
if (connfd < 0)
{
perror("accept4 error");
}


设置文件描述符为非阻塞

// non-block
int flags = fcntl(sockfd, F_GETFL, 0);
flags |= O_NONBLOCK;
int ret = fcntl(sockfd, F_SETFL, flags);
if (ret < 0)
{
perror("fcntl O_NOBLOCK error");
}
// close-on-exec
flags = fcntl(sockfd, F_GETFD, 0);
flags |= FD_CLOEXEC;
ret = fcntl(sockfd, F_SETFD, flags);
if (ret < 0)
{
perror("fcntl FD_CLOEXEC");
}

这是传统获得非阻塞socket的方式,先通过socket和accept接口获得阻塞的socket,然后调用fcntl设置非阻塞标志。需要注意一点就是,设置前需要先获取以前的标志,然后把新标志添加进去,否则会把以前的标志清除,这自然会导致悲剧。



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: