2016-05-13 6 views
3

私はお互いに話をするようにクライアントとサーバーを設定しました。しかし、クライアントにエコーバックしようとするたびに、ソケットが切断されたように見えます。コードの多くはyolinuxのソケットチュートリアルから変更されています。また、私はsshを介してリモートでこれを実行しています。ソケットが一貫してC++を切断しています

クライアント:

#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); 

    } 

サーバー:

#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); 
} 

クライアントの出力:

./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: 

サーバー出力:

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

MSG_NOSIGNALフラグが指定されていない場合、サーバーはsend()でクラッシュします。これは、ソケットがもう一方の端で切断されたことを意味します。 send()/ recv()のペアの後にソケットが一貫して切断されるのはなぜですか?

私の提出では、読みやすさ/スタイル/純粋な愚かさについてはお詫び申し上げます。

ありがとうございました!サーバーで

答えて

6

、あなたが使用している:ここでは

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

sockは、リスニングソケットではなく、受け入れられたクライアントソケットです。代わりにsocksockConに置き換える必要があります(これは、recv()関数呼び出しで使用されており、動作しています)。

関連する問題