Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Klient, serwer i sockety - niby działa, niby nie

Ostatnio zmodyfikowano 2017-09-15 18:46
Autor Wiadomość
Szustarol
Temat założony przez niniejszego użytkownika
Klient, serwer i sockety - niby działa, niby nie
» 2017-09-11 19:58:52
Może najpierw kod:

Klient:
C/C++
#include <iostream>
#include <netinet/in.h>
#include <arpa/inet.h> //inet_pton
#include <unistd.h> //read
#define MAXLINE 4096

int main( int argc, char ** argv )
{
    if( argc != 2 ) {
        std::cerr << "usage: a.out <IPaddress>\n";
        exit( 0 );
    }
   
    int sockfd, n;
    char recvline[ MAXLINE + 1 ];
    if(( sockfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
        std::cerr << "socket error\n";
        exit( 0 );
    }
   
    sockaddr_in servaddr = { };
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons( 13 );
   
    if( inet_pton( AF_INET, argv[ 1 ], & servaddr.sin_addr ) <= 0 ) {
        std::cerr << "inet_pton error for " << argv[ 1 ] << "\n";
        exit( 0 );
    }
   
    if( connect( sockfd,( sockaddr * ) & servaddr, sizeof( servaddr ) ) < 0 ) {
        std::cerr << "Connection error\n";
        exit( 0 );
    }
   
    while(( n = read( sockfd, recvline, MAXLINE ) ) > 0 ) {
        recvline[ n ] = 0;
        std::cout << recvline << std::endl;
    }
   
    if( n < 0 ) {
        std::cerr << "read error\n";
        exit( 0 );
    }
   
    return 0;
}
Serwer;
C/C++
#define MAXLINE 4096
#include <netinet/in.h> //sockaddr_in, socket, AF_INET, SOCK_STREAM
//INADDR_ANY
#include <iostream> //cerr, exit
#include <unistd.h> //read
#include <errno.h>


int main( int argc, char const * argv[] ) {
    int listenfd, connfd;
    sockaddr_in servaddr = { };
    std::string result;
    time_t ticks;
   
    if(( listenfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    {
        std::cerr << "socket error" << '\n';
        exit( 0 );
    }
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
    servaddr.sin_port = htons( 13 );
   
    if( bind( listenfd,( sockaddr * ) & servaddr, sizeof( servaddr ) ) < 0 ) {
        std::cerr << "bind error" << errno << '\n';
        exit( 0 );
    }
   
    if( listen( listenfd, 1024 ) < 0 )
    {
        std::cerr << "listen error" << '\n';
        exit( 0 );
    }
   
    for(;; ) {
        if( connfd = accept( listenfd,( sockaddr * ) NULL, NULL ) < 0 )
        {
            std::cerr << "accept error" << '\n';
            exit( 0 );
        }
       
        ticks = time( NULL );
        result = "Current time is: ";
        result += ctime( & ticks );
        result += "\r\n";
        if( write( connfd, & result[ 0 ], result.size() ) < 0 )
        {
            std::cerr << "write error" << '\n';
            exit( 0 );
        }
       
        if( close( connfd ) < 0 )
        {
            std::cerr << "close error" << '\n';
            exit( 0 );
        }
       
    }
   
    return 0;
}


Jak widać jest to daytime server i kient (Uczę się z książki unix network programming volume 1, wydanie 3).
No i wszystko fajnie, jak serwer jest już uruchomiony i klient podaje jego ip (w moim przypadku localhost) to otrzymuje zwrotnie wiadomość z czasem.
Tylko niestety, pierwsze takie zapytanie po uruchomieniu serwera sprawia, że czas jest wypisywany na konsolę (std out) serwera, klient się zacina, po czym
po wyłączeniu go przez Ctrl+c następne uruchomienie klienta powoduje już normalne wypisanie tekstu na stdout klienta.
W czym może być problem?

Edit, może to jakoś pomoże zrozumieć mój problem:
https://image.ibb.co/k1gjGv/Screenshot_20170911_200249.png[/img]
(https://image.ibb.co/k1gjGv/Screenshot_20170911_200249.png)
P-164801
baziorek
» 2017-09-11 22:07:14
W pełni Ci nie pomogę, ale zauważyłem, że funkcja accept() zwraca za pierwszym razem 0 (connfd wynosi 0), dlatego funkcja write() zapisuje na 0, a jest to standardowe wejście

EDYCJA:
Swoją drogą sprawdzałem Twojego klienta z kodem serwera z przykładu:
http://www.bogotobogo.com​/cplusplus​/sockets_server_client.php
i nie było tego problemu, ale nie zajmowałem się poprawianiem Twojego przykładu, może musisz jednak podać jakieś nienullowe argumenty do funkcji accept()
P-164812
j23
» 2017-09-12 14:50:43
if( connfd = accept(...) < 0 )
Widzisz teraz błąd? ;)
P-164833
Szustarol
Temat założony przez niniejszego użytkownika
» 2017-09-13 19:33:23
tak, prawdopodobnie powinno być accept <= 0 a nie < 0, ale w książce jest tylko < 0 dlatego mnie to zastanawia. Ktoś może uczył się z tej samej książki? A może da się jakoś wyłączyć to, że za 1. razem zwraca 0?
P-164849
Luq
» 2017-09-13 22:51:26
A może po prostu operator
<
 ma wyższy priorytet od
=
 ;)
P-164864
Breakermind
» 2017-09-15 18:46:08
Nie marnuj czasu na sockety bez tls/ssl (cały świat zasuwa na tls/ssl).
Tu są gotowce działające na tredach i processach z tls/ssl:
http://cpp0x.pl/forum/temat/?id=25796
P-164922
« 1 »
  Strona 1 z 1