TCP服务器没有正确接收数据
下面的代码在C和Qt C++中有TCP服务器。我的问题是我使用TCP来保证可靠性,但它有数据丢失(不是数据包)。在我的主代码中,如果我运行tcp客户端发送数据,TCP服务器只接收一个数据包。如果我在每个数据包传输之间向客户端添加sleep(1);
,则TCP服务器接收数据。客户端和服务器都在同一台计算机上运行。TCP服务器没有正确接收数据
为了简化问题,不能在这里放太多的代码,我有下面的代码执行得更快,但它损失了数据包的最后10-15个字节。
TCP C客户机
的main.c
#include "socket_handler.h" //I didn't put the all includes here
#define PORT 22208
//tcp server
int main(void)
{
int sockfd;
uint32_t senderAddress = 2130706433; //127.0.0.1
if(connect_to_server_w_uint(&sockfd, senderAddress, PORT) < 0){
printf("error at line 454\n");
exit(1);
}
char data[] = "124b00068c158f$321$52712304$13.212779$0$O$0$0$b4$1$0$3$0$0$0$0$11$0$7$0$1$fe$f1$aaa9fffffffffd80$2132b00$eb460b5e$1$1$2016-02-22 03:01:00$0000-00-00 00:00:00$321$24754$321$13132$1$98$0$5.1$0$3c$64$1$96$4d$3e8$38$2$46$dc$4$3$f6$e6$17$0$e6$d3$1$0$e6$d3$2$0£";
char buffer[512];
int i=0;
for(i=0; i<1000; i++){
bzero(buffer, 512);
sprintf(buffer, "%d***%s -----",i,data);
send_data_to_server(&sockfd, buffer, strlen(data) +1);
printf("[%d]: data is sent\n", i);
}
close_connection(&sockfd);
return 0;
}
socket_handler.c
int connect_to_server(int *sockfd , struct in_addr senderAddress, uint16_t destPort){
struct sockaddr_in serv_addr;
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (*sockfd < 0)
//error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr = senderAddress;
serv_addr.sin_port = htons(destPort);
if (connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
printf("connection error line 1413\n");
close(*sockfd);
return -1;
}
return 0;
}
int connect_to_server_w_uint(int *sockfd, uint32_t senderAddress, uint16_t destPort){
struct sockaddr_in serv_addr;
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (*sockfd < 0){
printf("ERROR opening socket");
close(*sockfd);
return -1;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(senderAddress);
serv_addr.sin_port = htons(destPort);
if (connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
printf("ERROR connecting");
close(*sockfd);
return -1;
}
return 0;
}
int send_data_to_server(int *sockfd, char *message, uint16_t msgLength){
int n = write(*sockfd, message, msgLength);
if (n < 0){
printf("ERROR writing to socket");
return -1;
}
return 0;
}
int close_connection(int *sockfd){
close(*sockfd);
return 0;
}
Qt的C++ TCP服务器
MainWindow.cpp
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void ParseThePacket(QByteArray data);
private:
Ui::MainWindow *ui;
Server *server;
};
Client.h
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(QObject *parent = 0);
public slots:
bool connectToHost(QString host);
bool writeData(QByteArray data);
private:
QTcpSocket *socket;
};
Server.cpp
Server::Server(QObject *parent) : QObject(parent)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
if(server->listen(QHostAddress::Any, PORT)){
qDebug() << "tcp server started!";
}else{
qDebug() << "tcp server couldn't start listening";
}
}
void Server::newConnection()
{
qDebug() << "new connection";
while (server->hasPendingConnections())
{
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
}
}
void Server::disconnected()
{
qDebug() << "disconnected";
socket->deleteLater();
}
void Server::readyRead()
{
qDebug() << "readyRead";
QByteArray buffer = socket->readAll();
emit dataReceived(buffer);
}
下面是从TCP服务器输出的示例(qDebug的端部()输出):
00:00:00 $ 321 $二四七五四$ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3C $ $ 64 1 $ $ 96 4D $ 3E8 $ $ 38 2 $ $ 46直流$ 4 $ 3 $ F6 $ E6 $ $ 17 0 $ E6 $ D3 $ 1 $ 0 $ E6 $ D3 $ 996 *** 124b00068c158f $ 321 $五二七一二三〇四$ 13.212779 $ 0 $ö$ 0 $ 0 $ B4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ $ 11 0 $ 7 $ 0 $ 1 $ FE $ F1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03:01:00 $ 0000-00-00 00:00:00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ F6 $ E6 $ $ 17 0 $ E6 $ D3 $ 1 $ 0 $ E6 $ D3 $ 997 *** 124b00068c158f $ 321 $五千二百七十一万二千三百○四$ 13.212779 $ 0 $ö$ 0 $ 0 $ B4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ $ 11 0 $ 7 $ 0 $ 1 $ FE $ F1 $ aaa9fffffffffd80 $ 2132 b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03:01:00 $ 0000-00-00 00:00:00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ F6 E6 $ $ $ 17 0 $ë 6 $ D3 $ 1 $ 0 $ E6 $ D3 $ 998 *** 124b00068c158f $ 321 $五二七一二三〇四$ 13.212779 $ 0 $ö$ 0 $ 0 $ B4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ $ 11 0 $ 7 $ 0 $ 1 $ FE $ F1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016- 02-22 00:00:00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ e6 $ 17 $ 0 $ E6 $ D3 $ 1 $ 0 $ E6 $ D3 $ 999产品*** 124b00068c158f $ 321 $五二七一二三○四$ 13.212779 $ 0 $ö$ 0 $ 0 $ B4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ $ 11 0 $ 7 $ 0 $ 1 $ FE $ F1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03:01:00 $ 0000-00-00 00:00:00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ E6 $ $ 17 $ 0 $ E6 D3 $ 1 $ 0 $ E6 $ D3 $” 断开
问题1 与原始消息相比,它错过了(14字节)发送数据的“1 $ 0 $ e6 $ d3 $ 2 $ 0 $”部分。缺少信息的原因是什么?如何修复TCP服务器接收完整数据的代码。
问题2 当我在我使用相同的码作为大的代码和TCP服务器的一部分开头提到接收分组,当我把睡眠(1)的每个分组传输之间(否则它只接收第一个数据包)。它的原因是什么以及如何解决它?
我观察到Wireshark上的数据包传输是所有的TCP数据包都发送成功,但好像接收部分有问题。
我使用Ubuntu 15.04,内核3.19.0-69泛型,gcc版本4.9.2
int n = write(*sockfd, message, msgLength);
if (n < 0){
您只是检查write()
没有返回负值,表明有错误。
但是,套接字的write()
不保证写入所有请求的字节。在套接字上的write()
可能会返回一个正值,这里的值小于msgLength
,表示写入的请求字节数少于所请求的字节数。详细记录在write()
的手册页中。
您忽略了这种可能性,这就是您丢失数据的可能原因。在这种情况下,由你决定要做什么。通常的做法是简单地返回并尝试写入剩余的字节(也可能不会完整写入)。
同样,从套接字读取时,不能保证发件人写入套接字的所有内容都将以一个大写读取。您需要确认您的阅读器已经阅读了所有需要阅读的内容,并且如果阅读器需要更多数据,请继续从套接字读取,直到收到它。
是的,我在wireshark上看到发送的数据包丢失。谢谢。 – sven
readAll只是读取提供给当前时刻的所有数据。
哇,很多代码。请出示您的[MCVE]。 –