如何让TCP服务器以并行模式运行发送而无需等待回复?



am 尝试构建一个可以发送和接收数据的TCP服务器。我的代码运行良好,但我注意到服务器必须等到服务器回复才能发送另一个数据。如何使服务器一次接收多个请求并在以后回复它们。

我想要一些可以使服务器接收数据并保持静音的东西,然后稍后回复数据(如果正确的话(。服务器在端口 2019 的 127.0.0.1 上运行。最后,我需要添加信号以防止 Control-C 退出程序。

启动客户端使用 ./客户端 127.0.0.1 2019

我的服务器代码,

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> 
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 2019
#define MAXIMUM_CONNECTION 100
#define BUFFER_SIZE 1024
int main() {

int sockfd, clientSock, bytes, index = 0;
struct sockaddr_in serverAddr, clientAddr;
memset(&serverAddr, '', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(bind(sockfd, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) >= 0) {
printf("33[0;31m");
printf("n successfully binded the address to socket");
}
listen(sockfd, MAXIMUM_CONNECTION);
char buffer[BUFFER_SIZE], message[BUFFER_SIZE];
while(1) {
socklen_t clientAddrLen = sizeof(clientAddr);
if(clientSock = accept(sockfd, (struct sockaddr*) &clientAddr, &clientAddrLen)) {
printf("33[0;31m");
printf("n client accepted");
}
memset(buffer, '', sizeof(buffer));
memset(message, '', sizeof(message));
bytes = recv(clientSock, buffer, BUFFER_SIZE - 1, 0);
buffer[BUFFER_SIZE] = '';
printf("n Received data: ");
fputs(buffer, stdout);
printf("n Type data to send: ");

while((message[index++] = getchar()) != 'n');
message[BUFFER_SIZE] = 'n';
send(clientSock, message, sizeof(message), 0);
}
shutdown(sockfd, SHUT_RDWR);
}

我的客户端代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024
// #define PORT 10900
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("33[1;31m");
printf("Expecting 2 arguments %d given", argc - 1);
exit(0);
}
char *inputServer = argv[1];
int port = atoi(argv[2]), index = 0, activityCount = 0;
char buffer[BUFFER_SIZE], message[BUFFER_SIZE];
struct sockaddr_in serverAddr;
int sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), bytes;
if (sockfd >= 0)
{
printf("33[0;32m");
printf("n[%d] socket successfully createdn", activityCount++);
}
else
{
printf("33[1;31m");
printf("nFailed to create socket, client exitingn");
exit(-1);
}
memset(&serverAddr, '', sizeof(serverAddr));
serverAddr.sin_addr.s_addr = inet_addr(inputServer);
serverAddr.sin_port = htons(port);
serverAddr.sin_family = AF_INET;
if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) >= 0)
{
printf("33[0;32m");
printf("n[%d] client successfully connected to %s on port %dn", activityCount++, inputServer, port);
}
else
{
printf("33[0;31m");
printf("nFailed to connecting to server, client exitingn");
exit(-1);
}
while (1)
{
memset(buffer, '', sizeof(buffer));
memset(message, '', sizeof(buffer));
printf("Type your message here & press enter key: ");
while ((message[index++] = getchar()) != 'n')
;
message[BUFFER_SIZE] = '';
if (send(sockfd, message, sizeof(message), 0) > 0)
{
printf("33[0;32m");
printf("n[%d] client sent message to servern", activityCount++);
printf("nMessage Sent: (%s)n", message);
}
else
{
printf("33[1;31m");
printf("nFailed to sending to server, client exitingn");
exit(-1);
}
bytes = recv(sockfd, buffer, BUFFER_SIZE - 1, 0);
buffer[BUFFER_SIZE] = '';
if (bytes > 0)
{
printf("33[0;32m");
printf("n[%d] client received message from servern", activityCount++);
printf("nMessage Received: (%s)n", buffer);
}
else
{
printf("33[0;31m");
printf("nFailed to receive from server, client exitingn");
}
}
shutdown(sockfd, SHUT_RDWR);
}

TCP 缓冲区

TCP 堆栈将提供大型缓冲区来保存传输中的数据。这些缓冲区通常比用于管道的缓冲区大得多。从实际的角度来看,上面示例代码中的数据sending(最多 1K 数据(不会导致任何"等待"——数据将被缓冲,服务器将继续执行,即使客户端没有立即读取数据。

在某种程度上,这类似于写入文件 - 应用程序write将进入系统缓冲区,应用程序通常可以继续运行,而系统会清除对磁盘的更改。

处理 CTRL/C

添加调用以捕获(或忽略(SIGINT

#include <signal.h>
void int_handler(int sig) {
fprintf(stderr, "Ignoring Signal %dn", sig) ;
return ;
}
int main(...)
{
signal(SIGINT, SIG_IGN) ;      // Ignore Signal
signal(SIGINT, int_handler) ;  // Custom hander
}

最新更新