在linux上,当使用C执行与端口0(选择随机端口)的套接字绑定时,我得到错误98,地址已在使用中.怎么可能?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了在linux上,当使用C执行与端口0(选择随机端口)的套接字绑定时,我得到错误98,地址已在使用中.怎么可能?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5050字,纯文字阅读大概需要8分钟。
内容图文
![在linux上,当使用C执行与端口0(选择随机端口)的套接字绑定时,我得到错误98,地址已在使用中.怎么可能?](/upload/InfoBanner/zyjiaocheng/971/be5f943eb4c44d46a509ae3536cf9182.jpg)
因此,我们有一个长期存在的商业产品,这已经很成熟,我以前从未见过这类问题.我们使用客户端程序将数据发送到服务器.有时,由于客户环境中的防火墙,我们允许最终用户指定要绑定的出站端口范围,但是,在我看到的这个特定问题中,我们没有这样做,并且正在使用端口0来执行绑定.从我读过的所有内容来看,这意味着选择一个随机端口.但我无法找到的是,这对内核/操作系统意味着什么.如果我要求一个随机端口,那么它是如何使用的呢?
严格来说,只有src ip / src端口的唯一配对. dst ip / port使连接唯一.我相信可以使用相同的端口,如果与另一个目标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的数量.
解决方法:
因此,看起来这与系统耗尽可用端口有关,并且它被配置为只有大约9000个端口可用.
/etc/sysctl.conf中的此设置控制可用端口:
net.ipv4.ip_local_port_range = 9000 65500
第一个数字是起始端口,第二个是最大数字.这个例子是从未经改动的Suse Enterprise Linux服务器11.0中提取的.
报告此问题的我们的客户以这样的方式配置它在他们定义的范围内只有大约9000个端口可用,并且所有端口都在系统上使用.
希望这对未来的其他人有所帮助.
内容总结
以上是互联网集市为您收集整理的在linux上,当使用C执行与端口0(选择随机端口)的套接字绑定时,我得到错误98,地址已在使用中.怎么可能?全部内容,希望文章能够帮你解决在linux上,当使用C执行与端口0(选择随机端口)的套接字绑定时,我得到错误98,地址已在使用中.怎么可能?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。