C++ Read在几次操作后返回0
我在客户端和服务器之间有一个TCP多线程通信。我不知道为什么第三次使用read函数时它只给出0C++ Read在几次操作后返回0,c++,linux,pipe,posix,C++,Linux,Pipe,Posix,我在客户端和服务器之间有一个TCP多线程通信。我不知道为什么第三次使用read函数时它只给出0 客户端代码 我获得了登录和用户的正确读数,但在读取parola时,它只返回0,然后我才能在客户端窗口中输入内容。显示的代码中存在多个错误读取()返回0是观察到的最小问题。事实上,这可能只是所示代码中所有其他问题的最终结果,而不是真正的原因。第一个主要问题多次出现,最好的例子是服务器代码: write (fd, mesaj_catre_client, sizeof(mesaj_catre_client)
我获得了登录和用户的正确读数,但在读取parola时,它只返回0,然后我才能在客户端窗口中输入内容。显示的代码中存在多个错误<代码>读取()返回0是观察到的最小问题。事实上,这可能只是所示代码中所有其他问题的最终结果,而不是真正的原因。第一个主要问题多次出现,最好的例子是服务器代码:
write (fd, mesaj_catre_client, sizeof(mesaj_catre_client));
此代码正在写入套接字。这将完全忽略write()
中的返回代码。写入套接字时,您绝对不能保证所有内容都会写入套接字。您需要在此处写入sizeof(mesaj_catre_客户端)
字节数。很遗憾,你不能保证所有这些字节都会被写入write()
只能写入mesaj_catre_客户端的第一个字节,并返回1。或者写入此结构的一半,并返回实际写入的字节数。您的代码必须对此进行检查,但您的代码忽略了它,因此您不知道在这里到底写入了哪些套接字
必须检查每次调用write()
的返回值,并相应调整程序的逻辑。通常的解决方案是重复write()
,这一次是对剩余的字节
从套接字读取时会出现相同的逻辑错误:
if (read(sd, msg, 1024) < 0) {
所示代码为C++代码,使用C++类。现代C++是类型安全的。任何现代C++代码都不需要使用<代码> Malc C <代码>或<代码>免费< /代码>,或从<代码> Value*/COD>中转换。这在这里是必要的,因为您使用的是C API。应将其替换为类型安全的
std::thread
,并且无需malloc
或new
任何内容
但是所示代码的根本问题是它没有准备好,并且不能正确处理套接字的读/写语义,这对每个
read()
和write()
调用中读取和写入的内容几乎没有保证。您不能做出任何类型的假设,必须小心地实现正确的逻辑,以便从套接字写入和读取单个字节,并将它们组装到读取和写入的逻辑结构中。无论是read()
还是write()
都不能为您做到这一点,必须自己实现所有逻辑。如果您能将您的评论[和消息]从罗马尼亚语翻译成英语,可能会有所帮助。我之所以知道他们是罗马尼亚人,是因为我将:parametru functia executata de thread
放入谷歌翻译,然后返回:线程执行的参数函数。此外,这似乎是c++
而不是c
,因此您可能希望删除c
标记。但是,乍一看,您没有检查一些函数的返回值(例如读取
和写入
)。而且,(例如)你正在做:sprintf(mesaj_catre_客户,“引见我的帕罗拉:”);写入(fd、mesaj_catre_客户端、sizeof(mesaj_catre_客户端))代码>但是,您最好使用:size\u t len=sprintf(mesaj\u catre\u客户机,“Improducti parola:”);写入(fd,mesaj_catre_客户端,len+1)代码>。至少有两个主要问题:1。您总是写入整个缓冲区,因此如果用户输入“hi”,则发送“hi\0\0\0\0\0\0\0\0\0\0\0[…]”。2.您假设客户端的一次写入变成了服务器上的一次读取。一般来说,这是不正确的,当您写入大缓冲区并读取较小缓冲区时,这肯定是不正确的。由于您似乎需要基于行的协议,因此应该了解如何读取和写入行。由于您正在执行read(…,whatever,sizeof(whatever))
,您可能需要查看返回值,因为第一个read
可以读取第一条消息,但缓冲区具有第二条消息的初始部分。(例如)如果发送方发送了两条消息(例如hello
和world
),接收方可能会收到helloworld
作为第一条[也是唯一的]消息,因为它得到的是10个字节,而不是5个字节。请在代码注释中使用英语。您可能需要阅读更多有关的信息,包括。考虑使用或或部分。
void ConectareServer::Conectare(int arg) {
fd=arg;
cout<<fd;
memset(mesaj_catre_client, 0, 1024);
sprintf(mesaj_catre_client,
"Conectare reusita, pentru a continua, trebuie sa te loghezi. Sintaxa comenzilor este urmatoarea: \n<login>, pentru a realiza logarea la server\n"
"<quit>, pentru a inchide programul");
write(arg, mesaj_catre_client, sizeof(mesaj_catre_client));
VerifComanda(arg);
}
void ConectareServer::VerifComanda(int fd) {
memset(mesaj_catre_client, 0, 1024);
memset(mesaj_de_la_client, 0, 1024);
read(fd, mesaj_de_la_client, sizeof(mesaj_de_la_client));
printf("[server]Mesajul a fost receptionat...%s\n", mesaj_de_la_client);
if(strcmp(mesaj_de_la_client, "login")==0){
Logare client(fd);
client.Login();
cout<<"Intra in Logare";
}
if (strcmp(mesaj_de_la_client, "quit") == 0) {
sprintf(mesaj_catre_client, "Conexiune incheiata");
write(fd, mesaj_catre_client, sizeof(mesaj_catre_client));
}
if(strcmp(mesaj_de_la_client, "login") != 0 && strcmp(mesaj_de_la_client, "quit") != 0)
{
cout<<"Crash";
}
}
void Logare::Login() {
memset(mesaj_catre_client, 0, 256);
char user[10];
char parola[8];
sprintf(mesaj_catre_client,"Introduceti user-ul: ");
write (fd, mesaj_catre_client, sizeof(mesaj_catre_client));
read (fd, user, sizeof (user));
printf ("[server]Mesajul a fost receptionat...%s\n", user);
memset(mesaj_catre_client, 0, 256);
sprintf(mesaj_catre_client,"Introduceti parola: ");
write (fd, mesaj_catre_client, sizeof(mesaj_catre_client));
read (fd, parola, sizeof (parola));
printf ("[s]Mesajul a fost receptionat...%s\n", parola);
if(Verificare_Logare(user,parola) == 1)
{
// Logare reusita
Meniu client(fd, user);
client.MeniuAplicatie();
}
}
write (fd, mesaj_catre_client, sizeof(mesaj_catre_client));
if (read(sd, msg, 1024) < 0) {
td=(struct thData*)malloc(sizeof(struct thData));
// ...
static void *treat(void * arg)
{
struct thData tdL;
tdL= *((struct thData*)arg);