C++ UDP 客户端挂起问题

Issue with C++ UDP Client Hanging Up

我正在从事的项目使用 TCP 和 UDP 来创建文件传输协议。 TCP 连接生成一个随机端口,其中 returns 到客户端,然后客户端使用 UDP 连接到该端口号上的服务器。然后使用 UDP 将一个文本文件一次传输四个字符到服务器,服务器将发回大写的字符,然后在客户端显示。问题是客户端在等待服务器发回字符的大写版本时挂断了。我将在下面留下代码。代码中不起作用的部分在客户端和服务器文件的末尾被注释掉了。感谢您的帮助!

客户代码

// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>

using namespace std;

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

// Variables
int port = strtol(argv[2], NULL, 10);
string file = argv[3];
int r_port;
FILE* fp;
string fileString;
string dataBuffer;
int charCounter = 0;
char c;

// *** Declare TCP socket ***
int tcpsocket = 0;
tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
    cerr << "Can't create a socket";
    return 1;
}

// Get host IP address
struct hostent *s;
s = gethostbyname(argv[1]);

// Setting destination info
struct sockaddr_in server;
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);

// Connect to server
int connectRes = connect(tcpsocket, (sockaddr*)&server, sizeof(server));
if (connectRes == -1) {
    cerr << "Can't connect to socket";
    return 1;
}

// Sending data to server
char payload[512] = "117";
int sendRes = send(tcpsocket, payload, 512, 0);
if (sendRes == -1) {
    cerr << "Could not send to server";
    return 1;
}

// Receive r_port from server
memset(payload, 0, sizeof(payload));
recv(tcpsocket, payload, 512, 0);
r_port = strtol(payload, NULL, 10);
close(tcpsocket);

// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
    cerr << "Can't create a socket";
    return 1;
}

// Get host IP address
s = gethostbyname(argv[1]);

// Setting destination info
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);

// File manipulation
fp = fopen(file.c_str(), "r");
    while (c != EOF) {
        c = fgetc(fp);
        fileString += c;
        charCounter++;
    }
fclose(fp);

// UDP file transfer
for (int i = 4; i < 8; i++) {
    dataBuffer += fileString[i];
}

socklen_t slen = sizeof(server);
memset(payload, 0, sizeof(payload));
strcpy(payload, dataBuffer.c_str());

sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
if (sendRes == -1) {
    cerr << "Could not send to server";
    return 1;
}

// Receive ack
// slen = sizeof(server);
// memset(payload, 0, sizeof(payload));
// recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&server, &slen);
// cout << "Capitalized data: " << payload;

close(udpsocket);
return 0;
}

服务器代码

// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <cstdlib>
#include <time.h>
#include <ctype.h>

using namespace std;

// Variables
int r_port;
string fileData;

// Generate Random Port
int randomPort() {
    srand(time(NULL));
    return rand() % ((65535 - 1024) + 1) + 1024;
}

// Capitalization Function
string capitalize(char* payload) {
    int i = 0;
    char c;
    string charArr;
    while(payload[i]) {
        c = payload[i];
        charArr += toupper(c);
        i++;
    }
    return charArr;
}

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

    // Variables
    int port = strtol(argv[1], NULL, 10);

    // *** Declare TCP socket ***
    int tcpsocket = 0;
    tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
    if (tcpsocket == -1) {
        cerr << "Can't create a socket";
        return -1;
    }

    // Receive data
    struct sockaddr_in server;
    memset((char *) &server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(tcpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
        cerr << "Can't bind to IP/Port";
        return -2;
    }

    if (listen(tcpsocket, SOMAXCONN) == -1) {
        cerr << "Can't listen";
        return -3;
    }

    struct sockaddr_in client;
    char payload[512];
    socklen_t clen = sizeof(client);
    int clientSocket = accept(tcpsocket, (sockaddr*)&client, &clen);

    if (clientSocket == -1) {
        cerr << "Problem with client connecting";
        return -4;
    }
    recv(clientSocket, payload, 512, 0);

    // Check client data
    if (strtol(payload,NULL,10) == 117) {
        r_port = randomPort();
        cout << "Handshake detected. Selected the random port " << r_port << "\n";
        }
    else {
        cout << "Error occurred\n";
    }

    // Return random port
    memset(payload, 0, sizeof(payload));
    sprintf(payload,"%ld",r_port);
    int sendRes = send(clientSocket, payload, 512, 0);
    if (sendRes == -1) {
        cerr << "Could not send to server\n";
        return 1;
    }
    close(clientSocket);
    close(tcpsocket);

    // *** Declare UDP socket ***
    int udpsocket = 0;
    udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udpsocket == -1) {
        cerr << "Can't create a socket";
        return -1;
    }

    // Receive data
    memset((char *) &server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(r_port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(udpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
        cerr << "Can't bind to IP/Port";
        return -2;
    }

    clen = sizeof(client);
    memset(payload, 0, sizeof(payload));
    recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&client, &clen);

    fileData = capitalize(payload);
    cout << "Payload: " << fileData << "\n";

    // Send ack 
    // socklen_t slen = sizeof(server);
    // memset(payload, 0, sizeof(payload));
    // strcpy(payload, fileData.c_str());
    // sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
    // if (sendRes == -1) {
    // cerr << "Could not send to server";
    // return 1;
    // }

    close(udpsocket);
    return 0;
}
ssize_t sendto(**int sockfd**, const void *buf, size_t len, int flags,
               const struct **sockaddr *dest_addr**, socklen_t addrlen);

参考:https://linux.die.net/man/2/sendto

您的目标地址应该是:(sockaddr *) &client