linux c获取随机端口号,c - 在Linux上,当使用C与端口0(选择随机端口)执行套接字绑定时,我得到errno 98,地址已在使用中。 那怎么可能? - 堆栈内存溢出...

因此,我们有一个长期存在的商业产品,它已经建立了很好的地位,而且我以前从未见过此类问题。 我们使用客户端程序将数据发送到服务器。 有时,由于客户环境中的防火墙,我们允许最终用户指定要绑定的出站端口范围,但是,在我看到的这个特定问题中,我们没有这样做,而是使用端口0进行绑定。 从我阅读的所有内容中,这意味着选择一个随机端口。 但是我不知道的是,这对内核/操作系统意味着什么。 如果我要一个随机端口,那该如何使用呢? 严格来说,只有src ip / src端口和dst ip /端口的唯一配对才能使连接唯一。 我认为,如果要与另一个目标IP通信,则可以使用相同的端口,但这可能与此处无关。

而且,这并非在所有客户系统上都发生,只有某些系统会发生。 因此,这可能是某种形式的与负载相关的问题。 有人告诉我系统很忙。

这是我们正在使用的代码。 我省略了一些用于Windows的ifdef代码,并省略了绑定后的处理方式。

_SocketCreateClient(Socket_pwtP sock, SocketInfoP sInfo )

{

int nRetries; /* number of times to try connect() */

unsigned short port;

BOOL success = FALSE;

BOOL gotaddr = FALSE;

char buf[INET6_ADDRSTRLEN] ="";

int connectsuccess =1;

int ipv6compat =0;

#ifdef SOCKET_SEND_TIMEOUT

struct timeval time;

#endif /* SOCKET_SEND_TIMEOUT */

nRetries = sInfo->si_nRetries;

sock->s_hostName = strdup(sInfo->si_hostName);

#ifdef DEBUG_SOCKET

LogWrite(LogF,LOG_WARNING,"Socket create client");

LogWrite(LogF,LOG_WARNING,"Number of retries = %d", nRetries);

#endif

ipv6compat = GetIPVer();

if (ipv6compat == -1) /* ipv6 not supported */

gotaddr = GetINAddr(sInfo->si_hostName, &sock->s_sAddr.sin_addr);

else

gotaddr = GetINAddr6(sInfo->si_hostName, &sock->s_sAddr6.sin6_addr);

/* translate supplied host name to an internet address */

if (!gotaddr) {

/* print this message only once */

if ( sInfo->si_logInfo && ( sInfo->si_nRetries == 1 ) )

{

LogWrite(LogF, LOG_ERR,

"unable to resolve ip address for host '%s'", sInfo->si_hostName);

}

sock = _SocketDestroy(sock);

}

else {

if (ipv6compat == 1) /* ipv6 supported */

{

/* try to print the address in sock->s_sAddr6.sin6_addr to make sure it's good. from call above */

LogWrite(LogF, LOG_DEBUG2, "Before call to inet_ntop");

inet_ntop(AF_INET6, &sock->s_sAddr6.sin6_addr, buf, sizeof(buf));

LogWrite (LogF, LOG_DEBUG2, "Value of sock->s_sAddr6.sin6_addr from GetINAddr6: %s", buf);

LogWrite (LogF, LOG_DEBUG2, "Value of sock->s_sAddr6.sin6_scope_id from if_nametoindex: %d", sock->s_sAddr6.sin6_scope_id);

LogWrite (LogF, LOG_DEBUG2, "Value of sock->s_type: %d", sock->s_type);

}

/* try to create the socket nRetries times */

while (sock && sock->s_id == INVALID_SOCKET) {

int socketsuccess = FALSE;

/* create the actual socket */

if (ipv6compat == -1) /* ipv6 not supported */

socketsuccess = sock->s_id = socket(AF_INET, sock->s_type, 0);

else

socketsuccess = sock->s_id = socket(AF_INET6, sock->s_type, 0);

if ((socketsuccess) == INVALID_SOCKET) {

GETLASTERROR;

LogWrite(LogF, LOG_ERR, "unable to create socket: Error %d: %s", errno,

strerror(errno) );

sock = _SocketDestroy(sock);

}

else

{

/* cycle through outbound port range for firewall support */

port = sInfo->si_startPortRange;

while ( !success && port <= sInfo->si_endPortRange ) {

int bindsuccess = 1;

/* bind to outbound port number */

if ( ipv6compat == -1) /* ipv6 not supported */

{

sock->s_sourceAddr.sin_port = htons(port);

bindsuccess = bind(sock->s_id, (struct sockaddr *) &sock->s_sourceAddr,

sizeof(sock->s_sourceAddr));

}

else {

sock->s_sourceAddr6.sin6_port = htons(port);

inet_ntop(AF_INET6, &sock->s_sourceAddr6.sin6_addr, buf, sizeof(buf));

LogWrite(LogF, LOG_DEBUG,

"attempting bind to s_sourceAddr6 %s ", buf);

bindsuccess = bind(sock->s_id, (struct sockaddr *) &sock->s_sourceAddr6,

sizeof(sock->s_sourceAddr6));

}

if (bindsuccess == -1) {

GETLASTERROR;

LogWrite(LogF, LOG_ERR,

"unable to bind port %d to socket: Error %d: %s. Will attempt next port if protomgr port rules configured(EAV_PORTS).", port, errno, strerror(errno) );

/* if port in use, try next port number */

port++;

}

else {

/* only log if outbound port was specified */

if (port != 0)

{

if ( sInfo->si_sourcehostName ) {

LogWrite(LogF, LOG_DEBUG,

"bound outbound address %s:%d to socket",

sInfo->si_sourcehostName, port);

}

else {

LogWrite(LogF, LOG_DEBUG,

"bound outbound port %d to socket", port);

}

}

success = TRUE;

}

}

}

}

}

return(sock);

}

我们在日志文件中看到的错误如下所示。 它正在尝试2次,但都失败了:

protomgr [628453]:错误:无法将端口0绑定到套接字:错误98:地址已在使用中。 如果配置了protomgr端口规则(EAV_PORTS),将尝试下一个端口。

protomgr [628453]:错误:无法将端口绑定到套接字:错误98:地址已在使用中。 如果此消息来自protomgr,请考虑增加EAV_PORTS的数量。

protomgr [628453]:错误:无法将端口0绑定到套接字:错误98:地址已在使用中。 如果配置了protomgr端口规则(EAV_PORTS),将尝试下一个端口。

protomgr [628453]:错误:无法将端口绑定到套接字:错误98:地址已在使用中。 如果此消息来自protomgr,请考虑增加EAV_PORTS的数量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值