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: #include <iostream> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #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; #define MAXLINE 4096 #include <netinet/in.h>
#include <iostream> #include <unistd.h> #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) |
|
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ścieEDYCJA: Swoją drogą sprawdzałem Twojego klienta z kodem serwera z przykładu: http://www.bogotobogo.com/cplusplus/sockets_server_client.phpi 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() |
|
j23 |
» 2017-09-12 14:50:43 if( connfd = accept(...) < 0 ) |
Widzisz teraz błąd? ;) |
|
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? |
|
Luq |
» 2017-09-13 22:51:26 A może po prostu operator < ma wyższy priorytet od = ;) |
|
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
|
|
« 1 » |