2016-05-13 10 views
3

Ich habe einen Client und Server eingerichtet, um miteinander zu sprechen. Aber jedes Mal, wenn ich versuche, zurück zum Client zu sprechen, scheint der Socket getrennt zu sein. Ein großer Teil des Codes ist aus einem Socket-Tutorial über yolinux angepasst. Außerdem laufe ich das remote über ssh.Socket konsequent trennen C++

Auftraggeber:

#include <cerrno> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netinet/tcp.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <sys/select.h> 
#include <sys/time.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <errno.h> 
#include <iostream> 
#include <cstdlib> 
#include <stdlib.h> 
#include <strings.h> 
#include <string.h> 
#include <string> 
#include <sstream> 

using namespace std; 

main(int argc, char *argv[]) 
{ 

    if (argc != 3) { 
     cout << "exiting\n"; 
     exit(EXIT_FAILURE); 
    } 

    struct sockaddr_in remoteSocketInfo; 
    struct hostent *hPtr; 
    int socketHandle; 
    char *remoteHost = argv[1]; 
    int portNumber = atoi(argv[2]); 

    cout << "Welcome!\n"; 

    // create socket 

    if ((socketHandle = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) 
    { 
      cout << "Socket creation failed.\n"; 
      close(socketHandle); 
      exit(EXIT_FAILURE); 
    } 
    cout << "Socket created!\n"; 

    bzero(&remoteSocketInfo, sizeof(sockaddr_in)); // Clear structure memory 

    if ((hPtr = gethostbyname(remoteHost)) == NULL) 
    { 
     cerr << "System DN name resolution not configured properly.\n"; 
     cerr << "Error number: " << ECONNREFUSED << endl; 
     exit(EXIT_FAILURE); 
    } 

    // Load system information for remote socket server into socket data structures 

    memcpy((char*)&remoteSocketInfo.sin_addr, hPtr->h_addr, hPtr->h_length); 
    remoteSocketInfo.sin_family = AF_INET; 
    remoteSocketInfo.sin_port = htons((u_short)portNumber); // set port number 

    if (connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(sockaddr_in)) < 0) { 
     cout << "connection failed\n"; 
     close(socketHandle); 
     exit(EXIT_FAILURE); 
    } 

    cout << "Connected!\n"; 

    string input; 
    int message; 
    while (1) { 
     cout << "Please indicate rotation amount:"; 
     cin >> input; 
     if (input == "exit") { 
      close(socketHandle); 
      break; 
     } 

     char buf[input.length()+1]; 
     const char *conv_input = input.c_str(); 
     strcpy(buf, conv_input); 
     int bytes_sent = 0; 
     if ((bytes_sent = send(socketHandle, buf, strlen(buf)+1, 0)) < 0) { 
      char buffer[256]; 
      char * errorMessage = strerror_r(errno, buffer, 256); 
      cout << errorMessage << endl; 
      close(socketHandle); 
      exit(EXIT_FAILURE); 
     } 
     cout << "bytes sent: " << bytes_sent << endl; 

     int rc; 
     char buf2[input.length()+1]; 
     rc = recv(socketHandle, buf2, strlen(buf)+1, 0); 
     buf[rc] = (char)NULL; // Null terminate string 


     cout << "received: " << buf2 << endl; 
     cout << "bytes received: " << rc << endl; 

     } 

    close(socketHandle); 

    } 

Server:

#include <iostream> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <cstring> 
#define MAXHOSTNAME 256 

using namespace std; 

main(int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     cout << "not enough arguments, ex: ./CaesarCipherServer 9876\n"; 
     exit(EXIT_FAILURE); 
    } 

    struct sockaddr_in socketInfo; 
    char sysHost[MAXHOSTNAME+1]; // Hostname of this computer we're running on 
    struct hostent *hPtr; 
    int portNumber = atoi(argv[1]); 
    int sock; 

    bzero(&socketInfo, sizeof(sockaddr_in)); // Clear structure memory 

    // Get system information 
    gethostname(sysHost, MAXHOSTNAME); // Get this computer's hostname 

    if ((hPtr = gethostbyname(sysHost)) == NULL) 
    { 
     cerr << "System hostname misconfigured." << endl; 
     exit(EXIT_FAILURE); 
    } 

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     close(sock); 
     exit(EXIT_FAILURE); 
    } 

    // Load system info into socket data structures 

    socketInfo.sin_family = AF_INET; 
    socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Use any addr available 
    socketInfo.sin_port = htons(portNumber); // Set port number 

    // Bind the socket to a local socket address 

    if (bind(sock, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0) 
    { 
     close(sock); 
     perror("bind"); 
     exit(EXIT_FAILURE); 
    } 

    cout << "listening for initial connection \n"; 
    listen(sock, 1); 

    int sockConn; 
    if ((sockConn = accept(sock, NULL, NULL)) < 0) 
    { 
     exit(EXIT_FAILURE); 
    } else { 
     cout << "connection accepted!\n"; 
    } 

    int rc = 0; 
    char buf[512]; 

    cout << "about to receive message... \n"; 
    // rc is number of chars returned 
    rc = recv(sockConn, buf, 512, 0); 
    buf[rc] = (char)NULL; // Null terminate string 

    cout << "received: " << buf << endl; 
    cout << "rc: " << rc << endl; 


    int bytes_sent; 
    if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) { 
     cout << "error sending\n"; 
     close(sock); 
     exit(EXIT_FAILURE); 
    } 

    cout << "bytes sent: " << bytes_sent << endl; 

    close(sock); 
} 

Client-Ausgabe:

./CaesarCipherClient cs-ssh 9876 
Welcome! 
Socket created! 
socket handle : 3 
Connected! 
Please indicate rotation amount:5 
bytes sent: 2 
received: 
bytes received: 0 
Please indicate rotation amount: 

Server Output:

./CaesarCipherServer 9876 
listening for initial connection 
connection accepted! 
about to receive message... 
received: 5 
rc: 2 
error sending 

Wenn das Flag MSG_NOSIGNAL nicht angegeben ist, stürzt der Server bei send() ab, was bedeutet, dass der Socket am anderen Ende getrennt wurde. Warum sollte der Socket nach einem send()/recv() -Paar immer wieder getrennt werden?

Ich entschuldige mich für schlechte Lesbarkeit/Stil/reine Dummheit in meinem Beitrag.

Vielen Dank für Ihre Hilfe!

Antwort

6

In Ihrem Server, den Sie verwenden:

if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) { 
     cout << "error sending\n"; 
     close(sock); 
     exit(EXIT_FAILURE); 
    } 

Hier sock ist die Abhörsocket, nicht die akzeptierte Client-Socket. Sie müssen stattdessen sock durch sockCon ersetzen (das Sie in Ihrem recv() Funktionsaufruf verwenden, und das funktioniert).