我是C编程新手,目前正在研究Unix套接字编程。
我的问题是实际绑定函数的第二个参数是什么?
int main(){
int mysocket;
int portno = 5004;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr, cli_addr;
struct sockaddr_in *p = &serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
bind(mysocket, p, sizeof(serv_addr));
}
我尝试传递p
,*p
,但它不起作用。
答案 0 :(得分:2)
bind()
的第二个参数是一个指向结构的指针,该结构描述了套接字要绑定到的本地接口(第三个参数是该结构的字节大小)。
bind()
将sockaddr*
指针作为输入,但它实际上接受与套接字的地址系列匹配的任何sockaddr_...
结构(sockaddr_in
AF_INET
,sockaddr_in6
为AF_INET6
,sockaddr_un
为AF_UNIX
等。
曾几何时,只有sockaddr
存在(对于AF_INET
)和BSD套接字API(特别是bind()
,accept()
,connect()
和{ {1}})围绕get(sock|peer)name()
设计。稍后,当引入新地址系列时,sockaddr
被创建为直接替换sockaddr_in
之前表示的地址(IPv4地址)。但套接字功能接口已经完成,无法更改。这就是调用这些函数时需要sockaddr
类型转换的原因。所有sockaddr*
结构(包括sockaddr_...
本身)都以16位sockaddr
标识符开头,因此使用此类型类型转换(与关联的字节大小参数协调)是安全的。 / p>
现在,在您的示例中,family
正在第二个参数中传递,p
被声明为p
,因此您实际上传递的内存地址为{{1} (此代码仅在参数声明为Struct sockaddr_in *p = &serv_addr;
时才会编译,否则您需要serv_addr
类型转换 - 这与平台有关!)。 void*
填充了IPv4地址(sockaddr*
,又名serv_addr
)和端口号(INADDR_ANY
,网络字节顺序)。第3个参数设置为0.0.0.0
。
因此,在该大小值和portno
设置为sizeof(serv_addr)
之间,serv_addr.sin_family
知道您传入了AF_INET
结构,并将相应地验证和使用它
答案 1 :(得分:0)
哎呀。从历史上看,起初只有struct sockaddr结构,后来发明了许多结构,例如:struc sockaddr_in,sockaddr_un结构。但是绑定函数已经设计了一个指针变量到第一个或开始结构sockaddr(历史上的第一个结构),现在我使用了sockaddr_in。 我看到成功绑定函数的唯一方法是:sockaddr * typecast:将类型的指针TYPECAST给另一个类型的指针。在我的例子是:类型转换指针p使用类型sockaddr_in到使用类型sockaddr的指针。如下所示:bind(mysocket,(struct sockaddr *)p,sizeof(serv_addr)),它可以工作。