相关疑难解决方法(0)

"同伴重置连接"是什么意思?

TCP连接上"通过对等连接重置"错误的含义是什么?这是致命错误还是只是通知或与网络故障有关?

sockets tcp

596
推荐指数
2
解决办法
74万
查看次数

服务器端的许多TIME_WAIT的成本是多少?

我们假设有一个客户端与服务器建立了很多短生命的连接.

如果客户端关闭连接,则客户端上将有许多TIME_WAIT状态的端口.由于客户端耗尽本地端口,因此无法快速进行新的连接尝试.

如果服务器关闭了连接,我会TIME_WAIT在服务器端看到很多s.但是,这有什么害处吗?客户端(或其他客户端)可以继续进行连接尝试,因为它永远不会耗尽本地端口,并且TIME_WAIT服务器端的状态数将增加.最终会发生什么?有什么不好的事吗?(减速,崩溃,掉线等)

请注意,我的问题不是"目的是TIME_WAIT什么?" 但是"如果TIME_WAIT服务器上有这么多状态,会发生什么?" 我已经知道在TCP/IP中关闭连接时会发生什么以及为什么TIME_WAIT需要状态.我不是想解决它,但只是想知道它的潜在问题.

简单来说,让我们说netstat -nat | grep :8080 | grep TIME_WAIT | wc -l打印100000.会发生什么?O/S网络堆栈是否会变慢?"打开文件太多"错误?或者,没什么好担心的?

tcp time-wait

61
推荐指数
3
解决办法
7万
查看次数

我如何使用setsockopt(SO_REUSEADDR)?

我在覆盆子pi上运行自己的http服务器.问题是当我停止程序并重新启动它时,端口不再可用.有时我在收到大量请求时会遇到同样的问题.
我想使用SO_REUSEADDR,以便即使出现错误但我也可以继续使用该端口但是没有运气设置它.以下是我的代码.
我得到的错误是"绑定时出错:地址已在使用中".

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

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
    printf("Starting Listener\n");
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET; …
Run Code Online (Sandbox Code Playgroud)

c sockets raspberry-pi

46
推荐指数
3
解决办法
11万
查看次数

流式传输Http请求的主体时如何处理错误

如何在Http消息中处理服务器错误?

假设我已经发送了消息的标题,并且我正在流式传输消息正文,当遇到意外错误时该怎么办.

我也假设这个错误是在生成内容而不是连接错误时引起的.

(很棒)简化代码:

// I can define any transfer encoding or header fields i need to.
send(header);  // Sends the header to the Http client.

// Using an iterable instead of stream for code simplicity's sake.
Iterable<String> stream = getBodyStream();
Iterator<String> iterator = stream.iterator();

while (iterator.hasNext()) {
    String string;
    try {
       string = iterator.next();   
    catch (Throwable error) { // Oops! an error generating the content.
        // What do i do here? (In regards to the Http protocol)
    }

    send(string); …
Run Code Online (Sandbox Code Playgroud)

protocols http

23
推荐指数
2
解决办法
2232
查看次数

关闭TcpListener和TcpClient连接的正确顺序(哪一方应该是活动关闭)

在上一个问题中读到了这个答案:

因此,启动终止的对等体 - 即首先调用close() - 将最终处于TIME_WAIT状态.[...]

但是,在服务器上处于TIME_WAIT状态的许多套接字可能会出现问题,因为它最终可能会阻止接受新连接.[...]

相反,请设计应用程序协议,以便始终从客户端启动连接终止.如果客户端总是知道它何时读取了所有剩余数据,则它可以启动终止序列.例如,浏览器在读取所有数据时可以从Content-Length HTTP标头中获知,并且可以启动关闭.(我知道在HTTP 1.1中它会保持打开一段时间以便重用,然后关闭它.)

我想使用TcpClient/TcpListener来实现它,但目前尚不清楚如何使其正常工作.

方法1:双方关闭

这是大多数MSDN示例所示的典型方式 - 双方调用Close(),而不仅仅是客户端:

private static void AcceptLoop()
{
    listener.BeginAcceptTcpClient(ar =>
    {
        var tcpClient = listener.EndAcceptTcpClient(ar);

        ThreadPool.QueueUserWorkItem(delegate
        {
            var stream = tcpClient.GetStream();
            ReadSomeData(stream);
            WriteSomeData(stream);
            tcpClient.Close();   <---- note
        });

        AcceptLoop();
    }, null);
}

private static void ExecuteClient()
{
    using (var client = new TcpClient())
    {
        client.Connect("localhost", 8012);

        using (var stream = client.GetStream())
        {
            WriteSomeData(stream);
            ReadSomeData(stream);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我运行20个客户端之后,套装软件显示了很多插座的客户端和服务器都 …

.net sockets tcplistener tcpclient

18
推荐指数
1
解决办法
5457
查看次数

为什么connect()会给EADDRNOTAVAIL?

我在我的应用程序中出现了一个似乎不可重现的故障.我有一个TCP套接字连接失败,应用程序尝试重新连接它.在第二次调用connect()尝试重新连接时,我得到了errno == EADDRNOTAVAIL的错误结果,connect()的手册页表示:"指定的地址不能从本地计算机上获得."

看看对connect()的调用,第二个参数似乎是错误引用的地址,但据我所知,这个参数是远程主机的TCP套接字地址,所以我对这个人感到困惑页面引用本地计算机.是否我的本地计算机无法访问远程TCP套接字主机的此地址?如果是这样,为什么会这样呢?它必须在连接失败之前第一次成功调用connect()并尝试重新连接并获得此错误.connect()的参数两次都是相同的.

这个错误会不会是一个短暂的错误,如果我等了很长时间,如果我再次尝试调用connect可能已经消失了?如果没有,我应该如何从这次失败中恢复?

c++ sockets linux tcp ip-address

13
推荐指数
1
解决办法
3万
查看次数

要关闭套接字,请不要关闭()套接字.Uhmm?

我知道TIME_WAIT是TCP/IP的一个组成部分,但是在SO(和其他地方)有很多问题,每秒创建多个套接字,服务器最终耗尽短暂的端口.

我发现的是,当使用TCPClient(或者Socket就此而言)时,如果我调用了Close()或者Dispose()方法,则套接字的TCP状态变为TIME_WAIT并且将在完全关闭之前考虑超时时间.

但是,如果只是将变量设置null为套接字将在下一次GC运行时完全关闭,这当然可以强制执行,而不会经历TIME_WAIT状态.

这对我来说没有多大意义,因为这是一个IDisposable对象不应该GC也调用Dispose()对象的方法?

这是一些PowerShell代码,演示了(在这台机器上没有安装VS).我使用Sysinternals的TCPView实时检查套接字状态:

$sockets = @()
0..100 | % {
    $sockets += New-Object System.Net.Sockets.TcpClient
    $sockets[$_].Connect('localhost', 80)
}

Start-Sleep -Seconds 10

$sockets = $null

[GC]::Collect()
Run Code Online (Sandbox Code Playgroud)

使用此方法,套接字永远不会进入TIME_WAIT状态.同样的,如果我只是手动调用之前关闭该应用程序Close()Dispose()

有人可以解释一下是否这是一个好习惯(我想人们会说这不是).

编辑

GC已经回答了这个问题,但我仍然有兴趣找出为什么这会对套接字状态产生任何影响,因为这应该由操作系统控制,而不是.NET.

还有兴趣了解使用此方法来防止TIME_WAIT状态并最终是否是某个地方的错误(即,所有套接字是否应该通过TIME_WAIT状态?)是否是一个好习惯?

.net c# sockets powershell

12
推荐指数
2
解决办法
2536
查看次数

为什么MongoDB在负载测试期间没有响应?

我有一个问题,MongoDB无法响应并拒绝生产中的连接.

在测试中,我能够通过向我的应用程序发送大量请求来一致地重现"锁定".

以下是mongostat的示例输出:

     0      0      0      0       0       1       0   1.3g   1.8g   177m      0        0          0       0|0     0|0    62b     1k    18   19:40:11
     0      0      0      0       0       1       0   1.3g   1.8g   177m      0        0          0       0|0     0|0    62b     1k    18   19:40:12
--------------LOAD TEST BEGINS-----------------------   
     1     56      0      0       1      58       0   1.3g  1.81g   177m      0        0          0       0|0     0|0    10k   302k    18   19:40:13
    10    116      0      0       2     127       0   1.3g  1.81g   177m      0        0          0       0|0     1|0    32k   263k …
Run Code Online (Sandbox Code Playgroud)

mongodb

8
推荐指数
1
解决办法
657
查看次数

尝试重新绑定已经关闭的侦听套接字失败(EADDRINUSE)?

以下是我的测试夹具的精髓 -

SetUp()
{
    g_listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    /* localhost is the server */
    bind(g_listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    listen(g_listen_sock, max_connections);
}

testcase()
{
    hdl = accept(g_listen_sock, NULL, NULL);
    -- send()/recv() data on the socket --
}

TearDown()
{
    shutdown(g_listen_sock, SHUT_RDWR);
    close(g_listen_sock);
    g_listen_sock = INVALID_SOCKET;
}
Run Code Online (Sandbox Code Playgroud)

在应用程序的正常使用中,侦听套接字仅在应用程序的生命周期中绑定一次,但是测试设置会反复打开和关闭侦听套接字.测试用例的第一次迭代工作正常但后续迭代在使用errno == 98ie EADDRINUSE 的bind()调用时失败.

我该如何避免这种情况?理想情况下,该解决方案不需要我具有单独的代码测试版本,例如在测试时使用SO_REUSEADDR.

PS - 相同的代码在Windows上正常工作,在Linux上发生bind()失败.

c sockets linux

3
推荐指数
1
解决办法
117
查看次数

当kill命令停止程序时关闭tcp套接字

我开发了一个包含一个小型http服务器的应用程序.

我的应用程序是在启动时启动的.如果应用程序正常停止(etc/init.d/myappli stop),套接字将被关闭

close (socket_desc); 
Run Code Online (Sandbox Code Playgroud)

但如果我用kill -9套接字杀死它将不会被关闭

http服务器代码:

void http_server_init(void)
{
    struct sockaddr_in server;
    int cr_port;

    for(;;) {
        cr_port = conf.port;
        int i = (DEFAULT_PORT == cr_port)? 1 : 0;
        //Create socket
        cr_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
        if (cr_socket_desc == -1)
        {
            LOG (ERROR,"Could not open server socket, Error no is : %d, Error description is : %s", errno, strerror(errno));
            sleep(1);
            continue;
        }

        /* enable SO_REUSEADDR */
        int reusaddr = 1;
        if (setsockopt(cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, …
Run Code Online (Sandbox Code Playgroud)

c sockets tcpsocket

2
推荐指数
1
解决办法
3825
查看次数

为什么带有 0 超时或 10 秒超时的 SO_LINGER 选项不会立即或在 10 秒后删除套接字?

我已阅读何时需要 TCP 选项 SO_LINGER (0)?以及其他几个相关的问题和答案,但我无法重现SO_LINGER这些帖子中解释的任何行为。我将在这里分享我的众多实验之一。

我正在以下环境中执行此实验。

$ lsb_release -d
Description:    Debian GNU/Linux 9.0 (stretch)
$ gcc -dumpversion
6.3.0
Run Code Online (Sandbox Code Playgroud)

这是一个行为不端的客户端连接到服务器,但在 90 秒内未收到任何数据的示例。

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

int main()
{
    int sockfd;
    int ret;
    struct addrinfo hints, *ai;
    char buffer[256];
    ssize_t bytes;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    if ((ret = getaddrinfo(NULL, "8000", &hints, &ai)) == -1) {
        fprintf(stderr, "client: getaddrinfo: %s\n", gai_strerror(ret)); …
Run Code Online (Sandbox Code Playgroud)

c sockets networking network-programming so-linger

2
推荐指数
1
解决办法
2921
查看次数