首页 > 解决方案 > 不可靠的 Unix 套接字连接

问题描述

我创建了一个基本的客户端/服务器 C++ 套接字程序。我可以可靠地在套接字上写入整数,但是当我尝试在套接字上写入字符串时,接收端只接收到大约 25% 的数据。我已经使用 Wireshark 来验证数据是否正在发送。我是 C++ 和网络编程的新手,所以任何输入都将不胜感激。代码如下。

class compressionServer{
    int                 PORT = 4000;
    int                 LISTEN_QUEUE = 1024;
    int                 sock;
    int                 conn;
    struct sockaddr_in  socketAddress;
    int                 receivedMagicData[8+1];
    int                 receivedStatusCode[2];
    int                 receivedPayloadLength[2];
    char                receivedCompressionData[2048];
    int                 requestCode = 0;
    int                 payloadLength;
    uint32_t            inBytes = 0;
    uint32_t            outBytes = 0;
    double              compressionRatio = 0;
    string              dataToCompress;

public:
    void start(){
        if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
            printf("Socket Error");
            exit(1);
        }

        bzero(&socketAddress, sizeof(socketAddress));
        socketAddress.sin_family      = AF_INET;
        socketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
        socketAddress.sin_port        = htons(PORT);
        int enable = 1;
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0){ // so we can rebind quickly while testing
            printf("setsockopt(SO_REUSEADDR) failed");
        }
        if(::bind(sock, (struct sockaddr *) &socketAddress, sizeof(socketAddress)) < 0){
            printf("Bind Error\n");
            std::cout << std::strerror(errno) << std::endl;
            exit(1);
        }


        if(listen(sock, LISTEN_QUEUE) < 0){
            printf("Listen Error");
            exit(1);
        }

        for ( ; ; ) {
            if((conn = accept(sock, (struct sockaddr *) NULL, NULL)) < 0){
                printf("Accept Error");
                exit(1);
            }
            ssize_t n;
            if((n = read(conn, receivedMagicData, 8)) > 0){
                int magicWord = ntohl(*receivedMagicData);

                if(magicWord == 53545259){
                    std::cout << "DOES NOT MATCH" << std::endl;
                    break;
                }

            }
            if((n = read(conn, receivedPayloadLength, 2)) > 0){
                payloadLength = ntohs(*receivedPayloadLength);

                std::cout << "payloadLength = " << std::hex << payloadLength << std::endl;
            }
            if((n = read(conn, receivedStatusCode, 2)) > 0){
                requestCode = ntohs(*receivedStatusCode);

                std::cout << "requestCode = " << std::hex << requestCode << std::endl;
            }
            while((n = read(conn, receivedCompressionData, 2048)) > 0){
                receivedCompressionData[n] = 0;
                cout << "data: " << receivedCompressionData << endl;
                dataToCompress = receivedCompressionData;
                if(strlen(receivedCompressionData) > 0){
                    break;
                }
            }

        }
        if (close(conn) < 0){
            printf("Close Error");
            exit(1);
        }
    }
};

基本的服务器类期望接收 12 个字节的数据作为标头,之后最多接收 2048 个字节作为字符。这只是一小部分时间。

class compressionClient{

public:
    void start(std::string  ipAddr){
        int                 MAX_LINE = 4096;
        int                 sockfd;
        struct sockaddr_in  servaddr;


        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
            printf("socket error");
            exit(1);
        }

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port   = htons(4000);


        if (inet_pton(AF_INET, ipAddr.c_str(), &servaddr.sin_addr) <= 0){
            printf("inet_pton error for %s", ipAddr.c_str());
            exit(1);
        }


        if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){
            printf("connect error");
            exit(1);
        }

        long headerHex = htonl(0x53545259);
        long header2Hex = htonl(0x31300034);

        std::cout << "send: " << std::hex << headerHex << std::endl;
        std::cout << "send2: " << std::hex << header2Hex << std::endl;
//server receives this
        if(send(sockfd, (char *) (&headerHex), sizeof(headerHex), 0) < 0){
            printf("Write Error");
            exit(1);
        }
//server receives this too 
        if(send(sockfd, (char *) (&header2Hex), sizeof(header2Hex), 0) < 0){
            printf("Write Error2");
            exit(1);
        }
        char data[100];
        snprintf(data, sizeof(data), "aaabbcddd");
//server only recieves this sometimes
        if(write(sockfd, data, strlen(data)) < 0){
            printf("write error3");
            exit(1);
        }
    }
};

标签: xcodemacossocketstcpc++14

解决方案


推荐阅读