我正在尝试编写一个使用tcp套接字与设备通信的C / C ++应用程序。我的应用程序充当服务器套接字。 从设备套接字接收数据时,服务器使用send()函数对设备做出响应:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
缓冲区长度(〜4kB)大于MTU(1500字节)。 TCP将其分为较小的程序包。我用wireshark捕获数据包。我看到tcp数据包之间的时间延迟是0.2-0.3s。如果我发送大数据(〜100Mb),则花费的时间太长(几个小时)。
我已经尝试通过setsockopt启用TCP_NODELAY,TCP_QUICKACK和TCP_CORK,但仍然无法减少时间延迟。
你们能帮我解决这个问题吗?
-------------------
编辑:
这是我的代码:
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
void createServerSocket();
void acceptConnect(int serverSock);
void receiveDataFromSocket(int socket);
void sendDataOverSocket(int clientSock);
void createServerSocket() {
int serverSockFd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
std::string address = "fd53:7cb8:383:5::68";
int port = 42654;
if (serverSockFd < 0)
{
printf("Create Server socket fail");
return;
}
struct sockaddr_in6 serverAddress;
(void)memset(&serverAddress, 0, sizeof(sockaddr_in6));
serverAddress.sin6_family = AF_INET6;
serverAddress.sin6_port = htons(port);
int result = inet_pton(AF_INET6, address.c_str(), &serverAddress.sin6_addr);
if (result <= 0)
{
printf("inet_pton() failed portnumber: %d, address: %s \n", port, address.c_str());
return;
}
// setting socket options
int flag = 1;
if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_QUICKACK ,(char *)&flag,sizeof(flag)) == -1)
{
printf("setsockopt TCP_QUICKACK failed for server socket on address %s \n", address.c_str());
}
if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_CORK,(char *)&flag,sizeof(flag)) == -1)
{
printf("setsockopt TCP_CORK failed for server socket on address %s \n", address.c_str());
}
if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_NODELAY,(char *)&flag,sizeof(flag)) == -1)
{
printf("setsockopt TCP_NODELAY failed for server socket on address %s \n", address.c_str());
}
result = bind(serverSockFd, (struct sockaddr*)&serverAddress, sizeof(sockaddr_in6));
if (result != 0)
{
printf("bind() failed portnumber: %d, address: %s \n", port, address.c_str());
return ;
}
result = listen(serverSockFd, 10);
if (result != 0) {
printf("listen() failed portnumber: %d, address: %s \n", port, address.c_str());
return ;
}
acceptConnect(serverSockFd);
}
void acceptConnect(int serverSock)
{
struct sockaddr_in6 clientAddress;
socklen_t len = sizeof(sockaddr_in6);
memset(&clientAddress, 0, sizeof(sockaddr_in6));
const int clientSocket = accept(serverSock, (struct sockaddr*)&clientAddress, &len);
if(clientSocket >= 0) {
char str_addr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(clientAddress.sin6_addr),
str_addr, sizeof(str_addr));
printf("New connection from: %s:%d ...\n", str_addr, ntohs(clientAddress.sin6_port));
receiveDataFromSocket(clientSocket);
}
}
void receiveDataFromSocket(int socket)
{
int SOCKET_BUFFER_MAX_SIZE = 8*1024;
char buffer[SOCKET_BUFFER_MAX_SIZE];
memset(buffer, '\0', SOCKET_BUFFER_MAX_SIZE);
//Receive data from sock
while (true) {
int dataLen = recv(socket, buffer, SOCKET_BUFFER_MAX_SIZE, 0);
printf("Receive data from socket: %d, msgLength = %d\n", socket, dataLen);
sendDataOverSocket(socket);
}
}
void sendDataOverSocket(int clientSock)
{
int dataLen = 4*1024 + 7;
char *buf = new char[dataLen];
memset(buf, 'a', 4*1024 + 7);
int ret;
ret = send(clientSock, buf, dataLen, 0);
if (ret <= 0) {
printf("ERROR Send message over socket");
return;
}
int error_code;
socklen_t error_code_size = sizeof(sockaddr_in6);
getsockopt(clientSock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
printf("Error code size: %d, error code: %d\n", error_code_size, error_code);
}
答案 0 :(得分:0)
我认为您已经超出了TCP发送缓冲区,正在按顺序接收和发送,如果另一端没有从套接字读取数据足够快,您将在每个send()操作中等待,直到发送缓冲区中有空间为止
检查您发送的信息是否比接收的信息多,我怀疑recv()正在读取小块数据(由于MTU),但是每个循环中大约发送4KB,因此您的recv / send调用没有达到适当的平衡。