一、socket函数函数的原型
int socket(int domain, int type, int protocol);
其中:
domain
参数指定套接字应该使用的协议族(例如,AF_INET
表示IPv4协议族)。type
参数指定套接字类型(例如,SOCK_STREAM
表示流套接字,用于TCP连接;SOCK_DGRAM
表示数据报套接字,用于UDP通信)。protocol
参数通常设置为0,表示使用默认的协议。
如果socket
函数成功创建了一个套接字,它将返回一个非负的套接字描述符(socket descriptor),可以用于后续的套接字操作(如连接、绑定、监听等)。如果函数失败,它将返回-1,并且可以通过查看全局变量errno
来获取错误码,以便进一步处理错误。
除了返回值之外,socket
函数还可能设置全局变量h_errno
以指示特定的主机端错误。但是,在现代的Linux系统中,通常使用getsockopt()
函数来获取套接字的选项和状态信息,而不是依赖h_errno
变量。
二、创建套接字的典型用法示例
#include <sys/types.h>
#include <sys/socket.h>
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
// 错误处理
perror("socket");
}
在上面的例子中,如果`socket`调用成功,`sockfd`将包含一个非负的文件描述符。如果调用失败,则会执行错误处理代码。
三、socket描述符是否会为0?
在Unix和Linux系统中,文件描述符(file descriptor)是一个非负整数,其中特定的值0、1、2通常被预留用作标准输入(stdin)、标准输出(stdout)和标准错误(stderr)流。当一个进程启动时,这三个文件描述符会默认分别被分配给这三个标准流。
因此,在大多数情况下,任何新创建的文件或套接字文件描述符将从3开始递增(假设没有手动关闭或更改过上述描述符)。这不是一个硬性的规则,但是在正常操作条件下,在调用`socket`等函数创建新的文件描述符时,系统会选择最小的、未被使用的非负文件描述符值。通常,这个值在正常程序运行时不会是0、1或2。
然而,如果程序关闭了标准输入、输出或错误(例如调用了`close(0);、close(1);或close(2);),那么下一次请求文件描述符的系统调用(比如socket`)可能会返回0、1或2,因为这些文件描述符号又重新变成可用的。为了避免这种情况的潜在混乱和错误,应该避免关闭这些特殊的文件描述符,除非有特别的理由并且有意识地处理它们。
所以,在一般程序设计实践中,如果`socket`调用成功,返回的文件描述符通常不会是0,除非程序已经关闭了标凈输入或其他与之相关的文件描述符。