比较 C 中的字符串 - strcmp
我在比较 C 语言中的字符串时遇到了麻烦(我对 C 语言还很陌生)。 我在这个服务器应用程序上有套接字等待接受来自客户端的数据。 在我的程序的这个特定部分中,我希望能够根据从客户端接收到的数据执行 MySQL 查询。 我希望能够知道接收到的数据何时具有“newuser”值以启动简单的注册过程。 Strcmp 返回正值 1,我相信我应该得到 0,因为这些值应该相等。
源代码:
//setup socket
//loop and select structure to handle multiple connections
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("selectserver: socket %d hung up\n", i);
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
char check[] = "newuser";
char fromUser[sizeof check];
strncpy(fromUser,buf, sizeof check);
printf("length of fromUser: %d\n", sizeof fromUser);
printf("length of check: %d\n", sizeof check);
printf("message from user: %s\n", fromUser);
printf("check = %s \n", check);
int diff = strcmp(fromUser, check);
printf("compare fromUser to check: %d\n", diff);
if ( strcmp(fromUser, check) == 0) {
printf("aha! new user");
}
输出:
length of fromUser: 8
length of check: 8
newuser from user: newuser
check = newuser
compare fromUser to check:
我有一种感觉,我没有正确处理传入缓冲区或错误地复制缓冲区。
I'm having trouble comparing strings in C (with which I am fairly new to). I have socket on this server application waiting to accept data from a client. In this particular portion of my program I want to be able to execute a MySQL query based on the data received from the client. I want to be able to know when the received data has the value of "newuser" to initiate a simple registration procedure. Strcmp is returning a positive 1 value where I believe I should be getting a 0 because the values should be equal.
Source Code:
//setup socket
//loop and select structure to handle multiple connections
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("selectserver: socket %d hung up\n", i);
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
char check[] = "newuser";
char fromUser[sizeof check];
strncpy(fromUser,buf, sizeof check);
printf("length of fromUser: %d\n", sizeof fromUser);
printf("length of check: %d\n", sizeof check);
printf("message from user: %s\n", fromUser);
printf("check = %s \n", check);
int diff = strcmp(fromUser, check);
printf("compare fromUser to check: %d\n", diff);
if ( strcmp(fromUser, check) == 0) {
printf("aha! new user");
}
Output:
length of fromUser: 8
length of check: 8
newuser from user: newuser
check = newuser
compare fromUser to check:
I have a feeling I'm not handling the incoming buffer correctly or erroneously copying the buffer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
strncpy
最多复制 - 在本例中 -sizeof
检查字节。 如果 nul 字节不在该范围内,则不会复制它。 您可能会将“newuser”一词作为较长句子的一部分,例如“newuser blah blah”,因此您需要自己放置该 nul或使用
strlcpy
(如果有)。strncpy
copies at most - in this case -sizeof
check bytes. If the nul byte is not in that range it is not copied. You probably are getting the word "newuser" as part of a longer sentence, like "newuser blah blah" so you need to place that nul yourselfor use
strlcpy
, if available.这是您在问题中给出的示例代码(删除了调试代码):
此代码是错误的; 您可能从 buf[] 复制的字节数多于已接收的字节数。 这将导致您与垃圾进行比较(可能碰巧与您的“newuser”字符串匹配)。 正如其他人所说,由于没有 NUL 终止字符串之一,您还有第二个错误。
在这种情况下,我将使用 memcmp()。 这类似于 strcmp(),但它需要一个长度参数,而不是期望以 NUL 结尾的字符串。
PS 不直接相关,但 recv() 可能会因返回 < code>-1 与
errno==EINTR
。 这不是错误情况,您只需重试。 通常这种情况很少发生,以至于人们在没有检查它的情况下就逃脱了,直到他们与其他使用信号的代码集成并且突然他们的代码随机失败。在基于
select()
的应用程序中,您还应该将套接字设置为非阻塞,然后检查errno==EAGAIN
,然后返回到>select()
在这种情况下。 如果 TCP/IP 堆栈收到损坏的数据包,就会发生这种情况 - 它认为它有一个数据包,因此select()
会告诉您它是可读的,只有当您尝试读取它时,TCP/IP堆栈进行校验和计算并意识到它必须丢弃数据。 然后它会阻塞(坏),或者如果它设置为非阻塞,那么它将返回-1
和errno==EAGAIN
。Here's the sample code you gave in your question (with debugging code removed):
This code is wrong; you're potentially copying more bytes from buf[] than have been received. This will lead to you comparing against garbage (that might by chance happen to match your "newuser" string). And as other people have said, you have a second bug due to not NUL terminating one of your strings.
In this case, I'd use memcmp(). This is like strcmp() but it takes a length parameter rather than expecting NUL-terminated strings.
P.S. Not directly related, but recv() can fail by returning
-1
witherrno==EINTR
. This isn't an error condition, you just need to try again. Normally this happens so rarely that people get away without checking it, until they integrate with some other code that uses signals and suddenly their code randomly fails.In a
select()
-based app, you should also be setting your sockets to non-blocking and then check forerrno==EAGAIN
, and go back to theselect()
in that case. This can happen if the TCP/IP stack receives a corrupted packet - it thinks it has a packet soselect()
will tell you it's readable, it's only when you try to read it that the TCP/IP stack does the checksum calculation and realises it has to throw away the data. It'll then either block (bad), or if it's set to nonblocking then it will return-1
witherrno==EAGAIN
.我相信这里的问题(这里的问题之一)是 fromUser (由于它的创建方式)不是 null 终止的。
I believe the problem here (one of the problems here) is that fromUser (due to the way it is created) is not null terminated.
您错过了 fromUser 末尾的 '\0' 字符:
You miss '\0' char at the end of fromUser:
需要进行两项更改:
Two changes required:
这段代码似乎关闭:
This code seems off:
用。。。来代替:
Replace with: