[英]UDP socket port allocation failure
我正在创建一个winsock UDP程序。 我正在使用的代码如下所示。
我总是收到端口分配错误。
我不明白为什么总是分配的端口为零。 如果有人可以帮助我...
void UDPecho(const char *, const char *);
void errexit(const char *, ...);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
void main(int argc, char *argv[])
{
char *host = "localhost";
char *service = "echo";
WSADATA wsadata;
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: UDPecho [host [port]]\n");
exit(1);
}
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
UDPecho(host, service);
WSACleanup();
exit(0);
}
void UDPecho(const char *host, const char *service)
{
char buf[LINELEN+1];
SOCKET s;
int nchars;
struct hostent *phe;
struct servent *pse;
struct protoent *ppe;
struct sockaddr_in sin, my_sin;
int type, status, client_port, size;
char *transport = "udp";
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
/* Map service name to port number */
if ( pse = getservbyname(service, transport) )
sin.sin_port = pse->s_port;
else if ( (sin.sin_port = htons((u_short)atoi(service)))== 0)
errexit("can't get \"%s\" service entry\n", service);
/* Map host name to IP address, allowing for dotted decimal */
if ( phe = gethostbyname(host) )
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit("can't get \"%s\" host entry\n", host);
printf("Our target server is at address %s\n", inet_ntoa(sin.sin_addr));
printf("The size of an FD set is %d\n", sizeof(FD_SET));
/* Map protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
errexit("can't get \"%s\" protocol entry\n", transport);
/* Use protocol to choose a socket type */
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
errexit("can't create socket: %d\n", GetLastError());
size = sizeof(sin);
memset(&my_sin, 0, sizeof(sin));
getsockname (s, (struct sockaddr *) &my_sin, &size);
client_port = ntohs(my_sin.sin_port);
if (client_port != 0)
printf ("We are using port %2d\n", client_port);
else {
printf("No port assigned yet\n");
}
}
void errexit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
UDP不会绑定到侦听端口,直到您在套接字上发出sendto()
或bind()
为止。 后者使您可以选择要监听的端口。 另一方面, Sendto()
将为您选择一个临时端口。 我希望在您执行以下两项操作之一之前,端口将保持为零。
经过评论后,我进一步研究了这一点。 根据Single UNIX规范 ,调用socket()
的结果是未绑定的套接字。 套接字是通过调用明确绑定 bind()
或隐含sendto()
将套接字的名称视为包含其(地址族,协议,本地IP地址和本地端口号)的元组。 前两个是在socket()
调用中指定的,后两个是通过bind()
调用的。 对于无连接协议,在断开连接的套接字上调用sendto()
将导致隐式绑定到OS选择的端口号。
最令人惊讶的是,我可以找到的唯一对此行为的引用是在Microsoft文档的sendto()
的备注部分中。
如果套接字未绑定,则系统会将唯一值分配给本地关联,然后将套接字标记为绑定。 在这种情况下,应用程序可以使用getsockname(Windows套接字)来确定本地套接字名称。
getsockname()
的单一UNIX规范指出:
如果套接字尚未绑定到本地名称,则未指定由address指向的对象中存储的值。
似乎未指定结果的成功返回是“标准”行为... hmmm ...我尝试过的所有实现均以套接字地址0.0.0.0:0成功返回,该地址对应于具有未指定端口的INADDR_ANY
。 在调用bind()
或sendto()
,尽管地址部分可能仍然是INADDR_ANY
,但getsockname()
返回填充的套接字地址。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.