TCP connect EADDRNOTAVAIL(99)错误原因分析
转自:http://blog.chinaunix.net/uid-20662820-id-3371081.html
关于TCP connect 返回错误99,可以能大家都会遇到,这里就分析一下这个错误的真正含义:
点击(此处)折叠或打开
- int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
- {
- struct inet_sock *inet = inet_sk(sk);
- struct tcp_sock *tp = tcp_sk(sk);
- struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
- struct rtable *rt;
- __be32 daddr, nexthop;
- int tmp;
- int err;
- if (addr_len < sizeof(struct sockaddr_in))
- return -EINVAL;
- if (usin->sin_family != AF_INET)
- return -EAFNOSUPPORT;
- nexthop = daddr = usin->sin_addr.s_addr;
- if (inet->opt && inet->opt->srr) {
- if (!daddr)
- return -EINVAL;
- nexthop = inet->opt->faddr;
- }
- tmp = ip_route_connect(&rt, nexthop, inet->saddr,
- RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
- IPPROTO_TCP,
- inet->sport, usin->sin_port, sk, 1);
- if (tmp < 0) {
- if (tmp == -ENETUNREACH)
- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
- return tmp;
- }
- if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
- ip_rt_put(rt);
- return -ENETUNREACH;
- }
- if (!inet->opt || !inet->opt->srr)
- daddr = rt->rt_dst;
- if (!inet->saddr)
- inet->saddr = rt->rt_src;
- inet->rcv_saddr = inet->saddr;
- if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
- /* Reset inherited state */
- tp->rx_opt.ts_recent = 0;
- tp->rx_opt.ts_recent_stamp = 0;
- tp->write_seq = 0;
- }
- if (tcp_death_row.sysctl_tw_recycle &&
- !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
- struct inet_peer *peer = rt_get_peer(rt);
- /*
- * VJ's idea. We save last timestamp seen from
- * the destination in peer table, when entering state
- * TIME-WAIT * and initialize rx_opt.ts_recent from it,
- * when trying new connection.
- */
- if (peer != NULL &&
- peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
- tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
- tp->rx_opt.ts_recent = peer->tcp_ts;
- }
- }
- inet->dport = usin->sin_port;
- inet->daddr = daddr;
- inet_csk(sk)->icsk_ext_hdr_len = 0;
- if (inet->opt)
- inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
- tp->rx_opt.mss_clamp = 536;
- /* Socket identity is still unknown (sport may be zero).
- * However we set state to SYN-SENT and not releasing socket
- * lock select source port, enter ourselves into the hash tables and
- * complete initialization after this.
- */
- tcp_set_state(sk, TCP_SYN_SENT);
- err = inet_hash_connect(&tcp_death_row, sk);
- if (err)
- goto failure;
- err = ip_route_newports(&rt, IPPROTO_TCP,
- inet->sport, inet->dport, sk);
- if (err)
- goto failure;
- /* OK, now commit destination to socket. */
- sk->sk_gso_type = SKB_GSO_TCPV4;
- sk_setup_caps(sk, &rt->u.dst);
- if (!tp->write_seq)
- tp->write_seq = secure_tcp_sequence_number(inet->saddr,
- inet->daddr,
- inet->sport,
- usin->sin_port);
- inet->id = tp->write_seq ^ jiffies;
- err = tcp_connect(sk);
- rt = NULL;
- if (err)
- goto failure;
- return 0;
- failure:
- /*
- * This unhashes the socket and releases the local port,
- * if necessary.
- */
- tcp_set_state(sk, TCP_CLOSE);
- ip_rt_put(rt);
- sk->sk_route_caps = 0;
- inet->dport = 0;
- return err;
- }
这里进入第84行代码的函数inet_hash_connect 查找一个本地可用端口与服务器建立连接
点击(此处)折叠或打开
- int inet_hash_connect(struct inet_timewait_death_row *death_row,
- struct sock *sk)
- {
- return __inet_hash_connect(death_row, sk, inet_sk_port_offset(sk),
- __inet_check_established, __inet_hash_nolisten);
- }
该函数实际上调用_inet_hash_connect
点击(此处)折叠或打开
- int __inet_hash_connect(struct inet_timewait_death_row *death_row,
- struct sock *sk, u32 port_offset,
- int (*check_established)(struct inet_timewait_death_row *,
- struct sock *, __u16, struct inet_timewait_sock **),
- void (*hash)(struct sock *sk))
- {
- struct inet_hashinfo *hinfo = death_row->hashinfo;
- const unsigned short snum = inet_sk(sk)->num;
- struct inet_bind_hashbucket *head;
- struct inet_bind_bucket *tb;
- int ret;
- struct net *net = sock_net(sk);
- if (!snum) {
- int i, remaining, low, high, port;
- static u32 hint;
- u32 offset = hint + port_offset;
- struct hlist_node *node;
- struct inet_timewait_sock *tw = NULL;
- inet_get_local_port_range(&low, &high);
- remaining = (high - low) + 1;
- local_bh_disable();
- for (i = 1; i <= remaining; i++) {
- port = low + (i + offset) % remaining;
- head = &hinfo->bhash[inet_bhashfn(net, port,
- hinfo->bhash_size)];
- spin_lock(&head->lock);
- /* Does not bother with rcv_saddr checks,
- * because the established check is already
- * unique enough.
- */
- inet_bind_bucket_for_each(tb, node, &head->chain) {
- if (ib_net(tb) == net && tb->port == port) {
- if (tb->fastreuse >= 0)
- goto next_port;
- WARN_ON(hlist_empty(&tb->owners));
- if (!check_established(death_row, sk,
- port, &tw))
- goto ok;
- goto next_port;
- }
- }
- tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
- net, head, port);
- if (!tb) {
- spin_unlock(&head->lock);
- break;
- }
- tb->fastreuse = -1;
- goto ok;
- next_port:
- spin_unlock(&head->lock);
- }
- local_bh_enable();
- return -EADDRNOTAVAIL;
- ok:
- hint += i;
- /* Head lock still held and bh's disabled */
- inet_bind_hash(sk, tb, port);
- if (sk_unhashed(sk)) {
- inet_sk(sk)->sport = htons(port);
- hash(sk);
- }
- spin_unlock(&head->lock);
- if (tw) {
- inet_twsk_deschedule(tw, death_row);
- inet_twsk_put(tw);
- }
- ret = 0;
- goto out;
- }
- head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)];
- tb = inet_csk(sk)->icsk_bind_hash;
- spin_lock_bh(&head->lock);
- if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
- hash(sk);
- spin_unlock_bh(&head->lock);
- return 0;
- } else {
- spin_unlock(&head->lock);
- /* No definite answer... Walk to established hash table */
- ret = check_established(death_row, sk, snum, NULL);
- out:
- local_bh_enable();
- return ret;
- }
- }
注意第61行代码,这里返回了EADDRNOTAVAIL错误。
点击(此处)折叠或打开
- void inet_get_local_port_range(int *low, int *high)
- {
- unsigned seq;
- do {
- seq = read_seqbegin(&sysctl_local_ports.lock);
- *low = sysctl_local_ports.range[0];
- *high = sysctl_local_ports.range[1];
- } while (read_seqretry(&sysctl_local_ports.lock, seq));
- }
然后内核在这个范围内选择一个可用的端口作为本地端口去connect服务器,如果没有可用的端口可用,比如这个范围内的端口都处于如下状态中的一种:
TCP connect EADDRNOTAVAIL(99)错误原因分析的更多相关文章
- loadFileSystems error & ExceptionUtils错误原因分析
loadFileSystems error & ExceptionUtils错误原因分析 一见 2014/5/7 C/C++程序通过hdfs.h访问HDFS,运行时遇到如下错误,会是什么原因了 ...
- “undefined reference to JNI_GetCreatedJavaVM”和“File format not recognized”错误原因分析
"undefined reference to JNI_GetCreatedJavaVM"和"File format not recognized"错误原因分析 ...
- SQL Server 磁盘请求超时的833错误原因分析以及解决
本文出处:http://www.cnblogs.com/wy123/p/6984885.html 最近遇到一个SQL Server服务器响应极度缓慢,并且出现客户端请求报错的情况,在数据库中的erro ...
- 微信的redirect_uri参数错误原因分析
我们可以根据微信的开发者文档 http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 网页授权获取用户验证这一章来 ...
- Entity Framework 数据并发访问错误原因分析与系统架构优化
博客地址 http://blog.csdn.net/foxdave 本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍 1. 发现问题 系统新模块上 ...
- 启动Hadoop HDFS时的“Incompatible clusterIDs”错误原因分析
"Incompatible clusterIDs"的错误原因是在执行"hdfs namenode -format"之前,没有清空DataNode节点的data目 ...
- Apache ab压力测试时出现大量的错误原因分析
最近有一个测试任务,是测试nginx的并发请求到底能够达到多少的, 于是就用ab工具对其进行压力测试. 这压力测试一执行,问题就来了:发起10000次请求,并发100,错误的情况能达到30%--50% ...
- FTP上传文件提示550错误原因分析。
今天测试FTP上传文件功能,同样的代码从自己的Demo移到正式的代码中,不能实现功能,并报 Stream rs = ftp.GetRequestStream()提示远程服务器返回错误: (550) 文 ...
- golang学习遭遇错误原因分析续
7. error: reference to field ‘Printf’ in object which has no fields or methods f.Printf("%v&quo ...
随机推荐
- 简化MonoTouch.Dialog的使用
读了一位园友写的使用MonoTouch.Dialog简化iOS界面开发,我来做个补充: 相信使用过DialogViewController(以下简称DVC)的同学都知道它的强大,但是缺点也是明显的,应 ...
- 重温HTML的基础
新年新气象,新的一年要有自己的学习计划与工作计划.希望大家能够共享. 经过一段时间,我想重新复习与学习一下HTML的基础,我呢打算整理一下W3C里面的知识,也许对某些人没有任何作用,但是对我来说这是我 ...
- [Usaco2008 Dec]Hay For Sale 购买干草[01背包水题]
Description 约翰遭受了重大的损失:蟑螂吃掉了他所有的干草,留下一群饥饿的牛.他乘着容量为C(1≤C≤50000)个单位的马车,去顿因家买一些干草. 顿因有H(1≤H≤5000)包 ...
- DedeCms密码解密[转]
dede 的密码怎么破解,dede后台.32位的DEDE密码如何破解 dede 的密码是32位MD5减去头5位,减去尾七位,得到20 MD5密码,方法是,前减3后减1,得到16位MD5. 比如我的数据 ...
- MyEclipse从数据库表反向生成实体类之Hibernate方式(反向工程)
一.打开Myeclipse Database Explorer 二.新建[New..] 三.选择数据库,添加驱动 四.测试连接 五.选中数据库中的表单击右键选择[Hibernate Rever..] ...
- 自己动手写spring容器(2)
上篇我们自己写了一个很简单的spring容器,该容器只是做了简单的bean的实例化,并没有spring的核心之一的IOC(依赖注入),也叫做控制反转,这里我就不讲这个的具体含义,不知道的园友可以自行百 ...
- A*算法&博弈树α-β剪枝
A*算法&博弈树α-β剪枝 A*算法/博弈树 前阵子考试学了A*算法.博弈树和回溯,自己真是愚蠢至极,根本没就搞明白这些,所以对于这些算法问道的话就不能说清楚,也记不住,所以才有了这篇笔记.在 ...
- android 弹出带输入框的对话框
private void inputTitleDialog() { final EditText inputServer = new EditText(this); inputServ ...
- poj1463 Strategic game (树状dp)
Strategic game Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 5498 Accepted: 2484 De ...
- POJ 1915 经典马步 双向bfs
拿这个经典题目开刀...........可是双向时间优势在这题上的效果不太明显 #include <iostream> #include <algorithm> #includ ...