Socket一直断开连接 C++

3
我有一个客户端和服务器已经建立了连接,但是每次我尝试回显给客户端时,套接字似乎都已经断开连接。很多代码都是从yolinux的套接字教程中适配而来。此外,我是通过ssh远程运行这个程序。

客户端:

#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()对之后套接字会一直断开连接呢?
我对我的提交中可能存在的可读性、风格或纯愚蠢表示歉意。
感谢您的帮助!
1个回答

6

在您的服务器上,您正在使用:

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

这里的sock是监听socket,不是已经接受的客户端socket。你需要用sockCon来替换sock,它在你的recv()函数调用中被使用,并且那个是有效的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接