Forum: PC-Programmierung Connection reset by peer


von Carolin Z. (seobalis)


Lesenswert?

Hallo Leute,

ich versuche eine TCP Verbindung zwischen server und client zu bauen. 
Der Client soll so schnell wie möglich senden.

Die Verbindung brecht ab wenn ich in der client-Seite keine 
sleep(1)-funktion benutze, und ich bekomme die Meldung "Connection reset 
by peer". Wie kann ich diese Fehler korrigieren ohne sleep zu benutzen.?
Ich bedanke mich schon mal für euere Hilfe.

Grüße,
Carolin
1
// client code
2
i=0;
3
while(1){
4
  send_len = send(sock, (char*)&i, sizeof(unsigned int), 0);
5
  i++;
6
  if(send_len < 0){
7
    //printf("connection error\n");
8
    close(sock);
9
    exit(1);
10
  }
11
  //sleep(1);
12
}
13
14
15
16
//server code
17
while(1){
18
  recv_len = recv(connect_sock, (char*)&sequence, 10, 0);
19
  if(recv_len > 0){
20
    printf("recv a number = %d \n, sequence);
21
  }
22
  else{
23
    perror("recv():");
24
    close(connect_sock);
25
    close(sock);
26
    exit(1);
27
  }
28
}

von zwieblum (Gast)


Lesenswert?

da fehlt was - der rest des codes.

von Klaus W. (mfgkw)


Lesenswert?

zwieblum hat Recht.

Mit dem restlichen Code wird es aber auch nicht gehen, weil recv()
meines wissens nicht wartet, bis eine Nachricht zum Lesen da ist.
D.h. wenn der Sender auch nur einmal nicht nachkommt, liefert recv()
gleich 0 und der Server macht ein close(); für den Client ist das
dann der "reset by peer".

von Zwie B. (zwieblum)


Lesenswert?

tja, da würde der rest des codes aufschluss geben, ob der socket 
blocking ist oder nicht ...

von Karl H. (kbuchegg)


Lesenswert?

Ob blocking oder nicht, eine zumindest rudimentäre Auswertung des 
Returncodes würde schon helfen
1
while(1){
2
  recv_len = recv(connect_sock, (char*)&sequence, 10, 0);
3
  if(recv_len > 0){
4
    printf("recv a number = %d \n, sequence);
5
  }
6
  else if( recv_len == 0 ) {    // sender has shut down
7
    perror("recv():");
8
    close(connect_sock);
9
    close(sock);
10
    exit(1);
11
  }
12
  else {
13
    switch( errno ) {
14
      case EBADF:
15
        perror( "s is an invalid descriptor.\n" );
16
        break;
17
18
      case ECONNABORTED:
19
        perror( "The virtual circuit was aborted because of a timeout or other failure.\n" );
20
        break;
21
22
      case ECONNRESET:
23
        perror( "The virtual circuit was reset by the remote host executing a hard or abortive close.\n" );
24
        break;
25
      case EFAULT:
26
        perror( "buf is an invalid pointer.\n" );
27
        break;
28
29
      case EINTR:
30
        perror( "A signal interrupted the recv() call.\n" );
31
        break;
32
33
      case EINVAL:
34
        perror( "The socket was not bound using bind(), or an invalid flag was specified, or len was 0 or negative.\n" );
35
36
      case EMSGSIZE:
37
        perror( "The message was too large to fit the specified buffer.\n" );
38
39
      case ENETDOWN:
40
        perror( "The network subsystem has failed.\n" );
41
        break;
42
43
      case ENETRESET:
44
        perror( "The connection is broken; the remote host reset.\n" );
45
        break;
46
47
      case ENOTCONN:
48
        perror( "The socket is not connected.\n" );
49
        break;
50
51
      case ENOTSOCK:
52
        perror( "s is not a socket descriptor.\n" );
53
        break;
54
55
      case EOPNOTSUPP:
56
        perror( "MSG_OOB was specified on socket that does not support out of band data.\n" );
57
        break;
58
59
      case ESHUTDOWN:
60
        perror( "The socket has been shut down.\n" );
61
        break;
62
63
      case ETIMEDOUT:
64
        perror( "The connection has been dropped because of a network failure.\n" );
65
        break;
66
67
      case EWOULDBLOCK:
68
        break;  // receive would block, not very interesting
69
    }
70
  }
71
}

Selbiges senderseitig.

Gerade bei Netzwerksachen ist das Auswerten der Return und Fehlercodes 
eines der Dinge, die Licht ins Dunkel bringen können und auf die man nie 
verzichten sollte. Manchmal muss man auch die Fehlercodes senderseitig 
und empfängerseitig in der zeitlich richtigen Reihenfolge sehen, um 
rauszukriegen was da warum falsch gelaufen ist.
Auf dieses Feature zu verzichten, bedeutet das Stochern im Nebel dem 
Arbeiten bei gutem Licht vorzuziehen.

von Stephan M. (stephanm)


Lesenswert?

Hi, dass Du "connection reset by peer" als Fehler bekommst ist seltsam. 
Das riecht nach Firewall oder dergleichen. Um so wichtiger ist es 
tatsächlich mal alle Netzwerk-I/O-relevanten Aufrufe wie von Karl heinz 
Buchegger vorgeschlagen mit einer vollständigen und korrekten 
Fehlerbehandlung zu verbrähmen, so dass man die Fehlerursache ggf. nach 
dem Ausschlussverfahren finden kann.

(Allerdings verstehe ich Karl heinz's switch()-Konstrukt nicht... IMHO 
reicht doch perror("read") oder dergleichen.)

Funktioniert Dein Code denn, wenn Client und Server lokal auf ein und 
demselben Rechner laufen und auf diesem Rechner sämtliche 
möglicherweise störenden Komponenten wie Firewall (auch die von einer 
möglichen Antivirus-Software) und andere Netzwerksauereien (ich denke da 
an all das was neben klassischem Firewalling sonst noch mit iptables 
machbar ist) abgeschalten sind?

Eine andere Möglichkeit, die mir noch einfällt, ist die falsche 
Verwendung von close(2) oder die irrtümliche Verwendung von close(2) 
statt shutdown(2). Allerdings bin ich mir da nicht sicher, ob man dann 
"connection reset by peer" als Fehler beim Senden/Empfangen bekommen 
würde (eigentlich hätte ich auf einen anderen Fehler getippt).

> Der Client soll so schnell wie möglich senden.

Es gibt eine Reihe von Dingen die dazu beachtet werden sollten. Los 
gehts mit diversen Socket-Options (TCP_CORK, TCP_NODELAY, SO_xxxBUF 
fallen mir spontan ein), weiter über Blocking I/O vs. Async IO, 
select(2) vs. epoll(2) vs. sonstwas(X) bis hin zu Einstellungen, die 
global für das gesamte System vorzunehmen sind (Stichwort sysctl).

Stephan

von (prx) A. K. (prx)


Lesenswert?

Klaus Wachtler schrieb:

> Mit dem restlichen Code wird es aber auch nicht gehen, weil recv()
> meines wissens nicht wartet, bis eine Nachricht zum Lesen da ist.

Doch. Es sei denn der Socket wurde explizit auf nonblocking umgestellt.

von Carolin Z. (seobalis)


Lesenswert?

Hallo,

ich bedanke mich für euere Antworte. Ich habe den Fehlercode ausgewertet 
wie Karl heinz Buchegger geschrieben hat, und ich bekomme in 
Empfänge-Seite diese Meldung nach ein mal empfangen:

s is not a socket descriptor.
: Socket operation on non-socket

Falls diese Information helfen kann:

Socket ist auf blocking mode
Sender und Empfänger laufen auf demselben Rechner

von (prx) A. K. (prx)


Lesenswert?

Carolin Zapa schrieb:

> s is not a socket descriptor.
> : Socket operation on non-socket

Und das ist dir nicht deutlich genug? Was auch immer das ist, was du dem 
Aufruf übergibst, es ist kein korrekt und erfolgreich geöffneter Socket. 
Also liegt das Problem möglicherweise davor, wo der Socket herkommt, 
oder er wurde zwischenzeitlich wieder geschlossen.

von Carolin Z. (seobalis)


Lesenswert?

A. K. schrieb:
> Carolin Zapa schrieb:
>
>> s is not a socket descriptor.
>> : Socket operation on non-socket
>
> Und das ist dir nicht deutlich genug? Was auch immer das ist, was du dem
> Aufruf übergibst, es ist kein korrekt und erfolgreich geöffneter Socket.
> Also liegt das Problem möglicherweise davor, wo der Socket herkommt,
> oder er wurde zwischenzeitlich wieder geschlossen.

Ja. Das ist mir auch klar dass der Socket geschlossen wurde. Aber Es ist 
mir noch nicht klar wieso der geschlossen wurde und wo wird es gemacht? 
Wieso kommt das Problem nicht wenn ich in Sender-Seite ein 
Sleep-Funktion rufe.

von Karl H. (kbuchegg)


Lesenswert?

Carolin Zapa schrieb:

> Ja. Das ist mir auch klar dass der Socket geschlossen wurde. Aber Es ist
> mir noch nicht klar wieso der geschlossen wurde und wo wird es gemacht?

Dann wirf in deinen (zum größten Teil hier unbekannten) Code noch ein 
paar zusätzliche printf rein, die dir sagen, was in welcher Reihenfolge 
gemacht wird.
Debuggen ist zwar eine Kunst für sich, aber zumindest die Idee überall 
printf reinzugeben, damit einem das Programm mitteilt was es gerade 
macht, sollte eigentlich ziemlich naheliegend sein.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.