You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言中为TCP连接的客户端与服务端双向指定端口?

实现两端指定端口的TCP双连接模式

我想用C语言复现一种TCP连接模式,已成功实现请求线连接,但无法创建回复线那种两端均指定端口的连接,之前仅能指定连接的一端端口。

核心需求

请求线中,服务端在端口L被动监听,客户端主动发起连接;回复线中,服务端使用端口L+1主动发起连接,客户端在端口U被动监听。客户端需通过请求线将端口U告知服务端,请求线关闭时服务端关闭回复线。

初始代码文件

acc.h 头文件

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/uio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#define MAXLINE 4096
#define LISTENQ 1024
#define SERV_TCP_PORT   50090 // port L
#define CLI_TCP_PORT    50094 // port U
#define SA struct sockaddr
#define MAX_CLIENTS 10

服务端初始代码

#include "acc.h"

int main() {
    int listenSocket, connSocket, clientDataPort, dataSocket, conStat;
    struct sockaddr_in servAddr, clientAddr, dataAddr;
    char buffer[MAXLINE];
    socklen_t clientLen;
    ssize_t bytesRead;

    listenSocket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&servAddr, 0, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(SERV_TCP_PORT);

    bind(listenSocket, (SA*)&servAddr, sizeof(servAddr));

    listen(listenSocket, MAX_CLIENTS);

    printf("Server listening on port %d (Port L)...\n", SERV_TCP_PORT);

    clientLen = sizeof(clientAddr);
    connSocket = accept(listenSocket, (SA*)&clientAddr, &clientLen);

    printf("Client connected for control: %s : %d (Ephemeral Port)\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

    bytesRead = recv(connSocket, buffer, sizeof(buffer), 0);
    buffer[bytesRead] = '\0';

    clientDataPort = atoi(buffer);
    printf("Received client's data port: %d (Port U)\n", clientDataPort);

    close(connSocket);
    printf("request line closed\n");


    dataSocket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&dataAddr, 0, sizeof(dataAddr));
    dataAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    dataAddr.sin_port = htons(clientDataPort);

    if ((conStat = connect(dataSocket, (SA*)&dataAddr, sizeof(dataAddr))) < 0) {
        printf("connect failed\n");  // error connecting to remote socket
    } else {
        printf("Connected to client's data port: %d\n", clientDataPort);
    }

    close(dataSocket);

    return 0;
}

客户端初始代码

#include "acc.h"

int main() {
    int cliSocket, dataSocket, dataConnSocket;
    struct sockaddr_in servAddr, dataAddr;
    char buffer[MAXLINE];
    socklen_t dataLen;
    
    cliSocket = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servAddr, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    servAddr.sin_port = htons(SERV_TCP_PORT);

    connect(cliSocket, (SA*)&servAddr, sizeof(servAddr));
    
    printf("Connected to server for control on port: %d\n", SERV_TCP_PORT);

    sprintf(buffer, "%d", CLI_TCP_PORT);
    send(cliSocket, buffer, strlen(buffer), 0);

    close(cliSocket);
    printf("request line closed\n");

    dataSocket = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&dataAddr, sizeof(dataAddr));
    dataAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    dataAddr.sin_port = htons(CLI_TCP_PORT);

    bind(dataSocket, (SA*)&dataAddr, sizeof(dataAddr));

    listen(dataSocket, MAX_CLIENTS);

    printf("Client listening for data on port: %d...\n", CLI_TCP_PORT);

    dataLen = sizeof(dataAddr);
    if((dataConnSocket = accept(dataSocket, (SA*)&dataAddr, &dataLen)) < 0 ) {
    fprintf(stderr, "accept failed\n");
    exit (1);
    }
    
    printf("Server connected on data port: %d\n", CLI_TCP_PORT);
    printf("%s : %d\n", inet_ntoa(dataAddr.sin_addr), ntohs(dataAddr.sin_port));

    close(dataConnSocket);
    close(dataSocket);

    return 0;
}

修改后的服务端代码

我对服务端代码进行了修改,在创建数据连接前,给服务端的数据socket绑定了指定端口L+1:

#include "acc.h"

int main() {
    int listenSocket, connSocket, clientDataPort, dataSocket, conStat;
    struct sockaddr_in servAddr, servAddr1, clientAddr, dataAddr;
    char buffer[MAXLINE];
    socklen_t clientLen;
    ssize_t bytesRead;

    listenSocket = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servAddr, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(SERV_TCP_PORT);

    bind(listenSocket, (SA*)&servAddr, sizeof(servAddr));

    listen(listenSocket, MAX_CLIENTS);

    printf("Server listening on port %d (Port L)...\n", SERV_TCP_PORT);

    clientLen = sizeof(clientAddr);
    connSocket = accept(listenSocket, (SA*)&clientAddr, &clientLen);

    printf("Client connected for control: %s : %d (Ephemeral Port)\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

    bytesRead = recv(connSocket, buffer, sizeof(buffer), 0);
    buffer[bytesRead] = '\0';

    clientDataPort = atoi(buffer);
    printf("Received client's data port: %d (Port U)\n", clientDataPort);

    close(connSocket);
    printf("request line closed\n");

    dataSocket = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&dataAddr, sizeof(dataAddr));
    dataAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    dataAddr.sin_port = htons(clientDataPort);

    // VVVVVVVV CHANGES HERE VVVVVVVVV
    bzero(&servAddr1, sizeof(servAddr1));
    servAddr1.sin_family = AF_INET;
    servAddr1.sin_addr.s_addr = inet_addr("127.0.0.1");
    servAddr1.sin_port = htons(SERV_TCP_PORT+1);
    bind(dataSocket, (SA*)&servAddr1, sizeof(servAddr1));

    if ((conStat = connect(dataSocket, (SA*)&dataAddr, sizeof(dataAddr))) < 0) {
        printf("connect failed\n");  // error connecting to remote socket
    } else {
        printf("Connected to client's data port: %d\n", clientDataPort);
    }

    close(dataSocket);

    return 0;
}

疑问

修改后的代码似乎可行,但我想确认这是否为实现该需求的最佳方式。另外,希望有代码(比如printf())验证所有端口已正确指定并连接。


内容的提问来源于stack exchange,提问作者Echidno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:52:02