首页
登录 | 注册

TCP/IP:连接服务器失败(错误原因:Connection refused)

TCP/IP:连接服务器失败(错误原因:Connection refused)

Linux中,通过系统调用(system call) connect 连接指定服务器建立TCP连接。

connect 最常见的失败原因是 Connection refused

假设服务器IP是192.168.44.148,且并 未有 进程监听端口是12500时:

若有TCP连接请求包到达192.168.44.148,则192.168.44.148的内核将 回复RST包 给客户端。

此时,在客户端一侧看来就是connect连接失败,被服务端拒绝连接。

Code:

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd < 0)
    {
        fprintf(stderr, "create socket error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12500);
    if (inet_pton(AF_INET, "192.168.44.148", &server_addr.sin_addr) <= 0)
    {
        fprintf(stderr, "inet_pton error!!!\n");
        exit(1);
    }

    if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        fprintf(stderr, "socket connect error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }
    fprintf(stdout, "connect to server ok!\n");

    close(client_fd); // free connection

    return 0;
}

编译:

[jiang@localhost client]$ gcc -o client client.c 
[jiang@localhost client]$ ll
total 16
-rwxrwxr-x. 1 jiang jiang 8237 Jun 10 09:41 client
-rw-rw-r--. 1 jiang jiang  906 Jun 10 09:29 client.c

运行:

服务器主机:

[test1280@localhost ~]$ ifconfig | grep "inet addr"
          inet addr:192.168.44.148  Bcast:192.168.44.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0
[test1280@localhost ~]$ netstat -an | grep 12500

客户端主机:

[jiang@localhost client]$ ./client 
socket connect error=111(Connection refused)!!!

tcpdump抓取协议包:

[root@localhost ~]# tcpdump tcp port 12500 -i eth0 -s 0 -w jiang.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C2 packets captured
2 packets received by filter
0 packets dropped by kernel

wireshark分析jiang.cap:

1)

TCP/IP:连接服务器失败(错误原因:Connection refused)

客户端调用 connect,发起TCP连接建立请求到服务端。

2)

TCP/IP:连接服务器失败(错误原因:Connection refused)

服务器内核收到要连接本机12500端口的请求,发现并未有对应的监听SOCKET,于是回复RST到客户端。

3)

客户端调用 connect 失败,错误原因:Connection refused。


服务器Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BACKLOG 16

int main()
{
    // socket
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0)
    {
        fprintf(stderr, "create socket error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }

    int flag = 1;
    if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0)
    {
        fprintf(stderr, "socket setsockopt error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }

    // bind
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET; // IPv4
    server_addr.sin_port = htons(12500); // Port
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP
    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        fprintf(stderr, "socket bind error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }

    // listen
    if (listen(listen_fd, BACKLOG) < 0)
    {
        fprintf(stderr, "socket listen error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }
    fprintf(stdout, "server init ok, start to accept new connect...\n");

    // accept
    int client_fd = accept(listen_fd, NULL, NULL);
    if (client_fd < 0)
    {
        fprintf(stderr, "socket accept error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }
    fprintf(stdout, "accept one new connect!!!\n");

    char msg[1024] = "";
    // read client-FIN=1 EOF
    while (read(client_fd, msg, sizeof(msg)-1) == 0)
        break;
    close(client_fd);

    return 0;
}

编译:

[test1280@localhost server]$ gcc -o server server.c 
[test1280@localhost server]$ ll
total 16
-rwxrwxr-x. 1 test1280 test1280 9616 Jun 10 09:51 server
-rw-r--r--. 1 test1280 test1280 1555 Jun 10 09:50 server.c

运行:

[test1280@localhost server]$ ./server 
server init ok, start to accept new connect...
accept one new connect!!!
[test1280@localhost ~]$ ifconfig | grep "inet addr"
          inet addr:192.168.44.148  Bcast:192.168.44.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0
[test1280@localhost ~]$ netstat -an | grep 12500
tcp        0      0 0.0.0.0:12500               0.0.0.0:*                   LISTEN 
[jiang@localhost client]$ ./client 
connect to server ok!

即使当前主机有进程监听12500端口,connect依然有可能被拒绝连接

略微修改下服务器代码(不使用地址通配INADDR_ANY):

    // bind
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12500); // Port
    // if (inet_aton("0.0.0.0", &(server_addr.sin_addr)) != 1)
    // if (inet_aton("192.168.44.148", &(server_addr.sin_addr)) != 1)
    if (inet_aton("127.0.0.1", &(server_addr.sin_addr)) != 1)
    {
        fprintf(stderr, "inet_aton error!!!\n");
        exit(1);
    }
    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        fprintf(stderr, "socket bind error=%d(%s)!!!\n", errno, strerror(errno));
        exit(1);
    }

编译 && 运行:

[test1280@localhost server]$ gcc -o server server.c 
[test1280@localhost server]$ ll
total 16
-rwxrwxr-x. 1 test1280 test1280 9620 Jun 10 10:12 server
-rw-r--r--. 1 test1280 test1280 1737 Jun 10 10:12 server.c
[test1280@localhost server]$ ./server 
server init ok, start to accept new connect...
[test1280@localhost ~]$ ifconfig | grep "inet addr"
          inet addr:192.168.44.148  Bcast:192.168.44.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0
[test1280@localhost ~]$ netstat -an | grep 12500
tcp        0      0 127.0.0.1:12500             0.0.0.0:*                   LISTEN

此时,在服务器上虽然有进程监听12500端口,但是监听套接字的IP地址是127.0.0.1(在127.0.0.1地址上监听12500端口)。

如果我们在客户端主机(192.168.44.144)上向【192.168.44.148:12500】发起TCP连接请求,将会被拒绝:

[jiang@localhost client]$ ifconfig | grep "inet addr"
          inet addr:192.168.44.144  Bcast:192.168.44.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0
[jiang@localhost client]$ ./client 
socket connect error=111(Connection refused)!!!

被拒绝原因是在148服务器上不存在监听套接字【192.168.44.148:12500】,只有监听套接字【127.0.0.1:12500】。

如果我们在服务端主机(192.168.44.148)上向【127.0.0.1:12500】发起TCP连接请求,将会被允许:

修改客户端代码:

        struct sockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(12500);
        if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0)
        {
                fprintf(stderr, "inet_pton error!!!\n");
                exit(1);
        }

编译 && 运行:

[test1280@localhost client]$ ifconfig | grep "inet addr"
          inet addr:192.168.44.148  Bcast:192.168.44.255  Mask:255.255.255.0
          inet addr:127.0.0.1  Mask:255.0.0.0
[test1280@localhost client]$ gcc -o client client.c
[test1280@localhost client]$ ./client
connect to server ok!

总结:

connect 发起TCP连接请求被拒绝是由于目标服务器上无对应的监听套接字(IP && PORT)。

在哪个IP上监听哪个端口,^_^。


相关文章

  • 一份还热乎的蚂蚁金服面经(已拿Offer)!附答案!!
    本文来自我的知识星球的球友投稿,他在最近的校招中拿到了蚂蚁金服的实习生Offer,整体思路和面试题目由作者--泽林提供,部分答案由Hollis整理自知识星球<Hollis和他的朋友们>中「直面Java」板块. 经历了漫长一个月的 ...
  • 源码|详解分布式事务之 Seata-Client 原理及流程
    前言 在分布式系统中,分布式事务是一个必须要解决的问题,目前使用较多的是最终一致性方案.自年初阿里开源了Fescar(四月初更名为Seata)后,该项目受到了极大的关注,目前已接近 8000 Star.Seata 以高性能和零侵入的特性为目 ...
  • 本文总结一个目录提纲,只要是给自己看的,记录一下哪些东西已经总结过了. 闲谈IPv6-Loopback网口上的IPv6地址: https://blog.csdn.net/dog250/article/details/89333045 闲谈I ...
  • 贾扬清:我对人工智能方向的一点浅见
    阿里妹导读:作为 AI 大神,贾扬清让人印象深刻的可能是他写的AI框架Caffe ,那已经是六年前的事了.经过多年的沉淀,成为"阿里新人"的他,对人工智能又有何看法?最近,贾扬清在阿里内部分享了他的思考与洞察,欢迎共同探 ...
  • 电厂锅炉,火电厂三大主力设备之一.在电厂生产过程中发挥了极其重要的作用,是火电厂生产所必不可少的重要设备.但是,近些年,因为锅炉安全管控不到位而造成的事故屡有发生,给电厂的财产及人员的生命造成极大威胁.分析电厂锅炉的泄漏原因,制定有针对性的 ...
  • 阿里新一代分布式任务调度平台Schedulerx2.0破土而出
    1. 产品简介 Schedulerx2.0是阿里中间件自研的基于Akka架构的新一代分布式任务调度平台,提供定时.任务编排.分布式跑批等功能.使用Schedulerx2.0,您可以在控制台配置管理您的定时任务,查询历史执行记录,查看运行日志 ...

2020 jeepshoe.net webmaster#jeepshoe.net
13 q. 0.287 s.
京ICP备10005923号