Breakermind Temat założony przez niniejszego użytkownika |
C++ smtp serwer z tls/ssl z openssl i STARTTLS - BarracudaSMTP » 2017-10-02 21:30:58 Witam, jak przechwycić socket error gdy client się rozłączy? I też się zamyka gdy pojedyńczy klien sie rozłącza, dlaczego? #include <stdio.h> #include <stdlib.h> #include <string.h>
#include <unistd.h>
#include <sys/socket.h> #include <netinet/in.h>
#include <signal.h> #include <string> #include <iostream>
using namespace std;
#define PORT 5555
bool Contain( std::string str, std::string search ) { std::size_t found = str.find( search ); if( found != std::string::npos ) { return 1; } return 0; }
int main( int argc, char const * argv[] ) { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof( address ); char buffer[ 1024 ] = { 0 }; if(( server_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == 0 ) { perror( "socket failed" ); exit( EXIT_FAILURE ); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons( PORT ); if( setsockopt( server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,( char * ) & opt, sizeof( opt ) ) < 0 ) { perror( "setsockopt" ); exit( EXIT_FAILURE ); } if( bind( server_fd,( struct sockaddr * ) & address, sizeof( address ) ) < 0 ) { perror( "bind failed" ); exit( EXIT_FAILURE ); } if( listen( server_fd, 100 ) < 0 ) { perror( "listen" ); exit( EXIT_FAILURE ); } while( 1 ) { pid_t pid; int currpid = 0; if(( new_socket = accept( server_fd,( struct sockaddr * ) & address,( socklen_t * ) & addrlen ) ) < 0 ) { perror( "accept" ); exit( EXIT_FAILURE ); } pid = fork(); if( pid > 0 ) { currpid = pid; fprintf( stderr, "Mam mowego klienta, pid=%d\n", currpid ); } if( new_socket < 0 ) { perror( "Unable to accept" ); exit( EXIT_FAILURE ); } char * welcome =( char * ) "220 Hello ESMTP\r\n"; char * ehlo =( char * ) "250-bobo.pp at your service\r\n250-SIZE 157286400\r\n250 250-STARTTLS\r\n"; char * ok =( char * ) "250 Ok\r\n"; char * data =( char * ) "354 send data\r\n"; char * end =( char * ) "250 email was send\r\n"; char * bye =( char * ) "221 Bye...\r\n"; char * tls =( char * ) "220 Ready to start TLS\r\n"; buffer[ 0 ] = '\0'; memset( buffer, 0, sizeof( buffer ) ); send( new_socket, welcome, strlen( welcome ), 0 ); valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); memset( buffer, 0, sizeof( buffer ) ); send( new_socket, ehlo, strlen( ehlo ), 0 ); valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); memset( buffer, 0, sizeof( buffer ) ); send( new_socket, ok, strlen( ok ), 0 ); valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); memset( buffer, 0, sizeof( buffer ) ); send( new_socket, ok, strlen( ok ), 0 ); valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); memset( buffer, 0, sizeof( buffer ) ); send( new_socket, data, strlen( data ), 0 ); while( 1 ) { valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); if( Contain( std::string( buffer ), ".\r\n" ) ) { break; } } memset( buffer, 0, sizeof( buffer ) ); send( new_socket, end, strlen( end ), 0 ); valread = read( new_socket, buffer, 1024 ); printf( "Client send %s\n", buffer ); memset( buffer, 0, sizeof( buffer ) ); send( new_socket, bye, strlen( bye ), 0 ); close( new_socket ); } }
|
|
Gravity |
» 2017-10-02 23:40:39 Nie jestem pewny ale chyba nie ma SOCKET_ERRORA jeśli client się rozłączy. Natomiast możesz w pętli while sprawdzać ile bajtów zwróciła funkcja recv i jeśli ona jest równa 0 to możesz wtedy zamknąć połączenie na serwerze. |
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-10-03 09:12:57 Dzięki, coś jeszcze o funkcji select() wyczytałem (działanie na podobnej zasadzie). Posprawdzam jak tak. if( valread < 0 ) error( "ERROR reading from socket" );
http://man7.org/linux/man-pages/man2/read.2.html http://man7.org/linux/man-pages/man3/errno.3.html Lub: bzero( bufor, sizeof( bufor ) ); if(( recv( gniazdo, bufor, sizeof( bufor ), 0 ) ) <= 0 ) { perror( "recv() ERROR" ); exit( - 1 ); } printf( "|Wiadomosc z serwera|: %s \n", bufor );
shutdown( gniazdo, SHUT_RDWR );
Jest napisane: http://cpp0x.pl/artykuly/?id=66 |
|
j23 |
» 2017-10-03 10:20:11 Tak nawiasem, popraw pętlę na: while(( valread = read( new_socket, buffer, 1024 - 1 ) ) > 0 ) { buffer[ valread ] = 0; printf( "Client send %s\n", buffer ); if( Contain( std::string( buffer ), ".\r\n" ) ) { break; } }
|
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-10-03 10:29:55 Ok, jest jeszcze jeden problem w tym przykładzie: drugi i kolejny klient [telnet localhost 5555] nie chciał odbierać i wysyłać danych a jest fork() i nie wiem dlaczego? |
|
mateczek |
» 2017-10-03 12:29:55 Tą pętlę która jest umieszczona w kursie na stronie http://cpp0x.pl/kursy/Kurs-WinSock-C++/Tlo-Klient-Serwer/276jeszcze ogarniam logicznie. Jest wyraźnie rozdzielone co robi proces główny(serwera) a co robi proces dziecko dziecko 1. Dziekcko kasuje port nasłuchowy Dziecko to już nie serwer !!!! 2. A proces główny nie gada z klientem tylko robi accept i tworzy nowe sockety. 3 dziecko zawsze kończy proces, nie obróci pętlą while; while( 1 ) { sin_size = sizeof( struct sockaddr_in ); if(( new_fd = accept( sockfd,( struct sockaddr * ) & their_addr, & sin_size ) ) == - 1 ) { perror( "accept" ); continue; } printf( "server: got connection from %s\n", inet_ntoa( their_addr.sin_addr ) ); if( !fork() ) { close( sockfd ); if( send( new_fd, "Hello, world!\n", 14, 0 ) == - 1 ) perror( "send" ); close( new_fd ); exit( 0 ); } close( new_fd ); } |
|
Breakermind Temat założony przez niniejszego użytkownika |
C++ smtp serwer z tls/ssl z openssl i STARTTLS - BarracudaSMTP » 2017-10-05 21:13:38 Dzieki za help ;) I coś takiego małego stworzyłem, przykład serwera smtp z ssl na socket openssl z odpalaniem STARTTLS. Czyli server zaczyna jako serwer bez ssl po komendzie STARTTLS przechodzi w stan TLS/SSL i odbiera dane z innego serwera smtp lub z klienta. To tylko przykład i zapewne nie doskonały czyli nie zapisuje wiadomości i nie sprawdza poprawności nadawcy i odbiorcy, lecz wiadomości dochodzą z microsoft live, yahoo, ovh, opessl client, gmail ma jakieś wonty na ssl ale bez daje radę ;) może się jeszcze nauczy. I właśnie chodzi o sprawdzenie dlaczego google nie wysyła wiadomości na ssl a utyka po STARTTLS i wysłaniu EHLO do serwera (jakby się rozłączał)? https://github.com/breakermind/BarracudaSMTPCertyfikaty tls pobieram z https://www.sslforfree.com/ czyli testowałem na wpełni funkcjonalnych i dobrych ustawieniach revdns, mx, dkim i spf. Pozdrawiam |
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-10-06 14:09:49 Jednak działa i na gmail :).
|
|
« 1 » |