如何在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
相关产品推荐
相关产品推荐

