我在比较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:
我感觉我没有正确处理传入缓冲区或错误地复制缓冲区。
答案 0 :(得分:6)
strncpy
最多复制 - 在这种情况下 - sizeof
检查字节。如果nul字节不在该范围内,则不会复制。您可能会将“newuser”这个词作为较长句子的一部分,例如“newuser blah blah”,所以你需要自己放置那个
strncpy(fromUser, buf, sizeof check);
fromUser[sizeof check - 1] = '\0';
或使用strlcpy
(如果有)。
答案 1 :(得分:3)
以下是您在问题中提供的示例代码(删除了调试代码):
//setup socket
//loop and select structure to handle multiple connections
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
[... exception handling here ...]
} else {
char check[] = "newuser";
char fromUser[sizeof check];
strncpy(fromUser,buf, sizeof check);
if ( strcmp(fromUser, check) == 0) {
printf("aha! new user");
}
这段代码错了;你可能会从buf []中复制比收到的更多的字节。这将导致您与垃圾进行比较(可能碰巧匹配您的“newuser”字符串)。正如其他人所说,你有第二个错误,因为NUL没有终止你的一个字符串。
在这种情况下,我会使用memcmp()。这就像strcmp(),但它需要一个长度参数,而不是期望NUL终止的字符串。
//setup socket
//loop and select structure to handle multiple connections
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
[... exception handling here ...]
} else {
static const char check[] = "newuser";
const size_t check_len = sizeof(check) - 1; // exclude the NUL terminator
if (nbytes >= check_len && memcmp(buf, check, check_len) == 0) {
printf("aha! new user");
}
P.S。不直接相关,但-1
可能会因errno==EINTR
返回select()
而失败。这不是错误情况,您只需要再试一次。通常这种情况很少发生,人们在没有检查的情况下逃脱,直到他们与其他一些使用信号的代码集成,突然他们的代码随机失败。
在基于errno==EAGAIN
的应用中,您还应将套接字设置为非阻止,然后检查select()
,并在这种情况下返回select()
。如果TCP / IP堆栈收到损坏的数据包,就会发生这种情况 - 它认为它有一个数据包,因此-1
会告诉您它是可读的,只有在您尝试读取它时,TCP / IP堆栈才会进行校验和计算并意识到它必须扔掉数据。然后它会阻止(坏),或者如果它被设置为非阻塞,那么它将返回errno==EAGAIN
{{1}}。
答案 2 :(得分:2)
我认为这里的问题(这里的问题之一)是fromUser(由于它的创建方式)不是空终止。
答案 3 :(得分:2)
你在来自用户:
的末尾错过'\ 0'char...
strncpy(fromUser,buf, sizeof check);
fromUser[strlen(check)] = '\0';
答案 4 :(得分:1)
需要进行两项更改:
char fromUser[sizeof check] = {'\0'}; //Make all null characters
strncpy(fromUser,buf, sizeof check -1); //Last character is for null character.
答案 5 :(得分:0)
此代码似乎已关闭:
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0)
{
// your stuff
}
else {
const char *pCheck = "newuser";
char *fromUser = new char[nbytes];
strncpy(fromUser, buff, nbytes);
fromUser[nbytes] = '\0';
if(strcmp(fromUser,check)==0)
// blah
delete [] fromUser;
}
答案 6 :(得分:-1)
替换为:
char check[] = "newuser\0";