让我们向C-SERVER发送消息:
echo '1234567890' | nc <ip> <port>
C-SERVER打印:( oo.ooo.o =客户端的部分IP)
678oo.ooo.o---
但我只是要求它从来电信息中打印 3个字符 (从第五字符开始)
strncpy(ii2, iii + 5, 3);
它应该只是打印:(加上 --- )
678
问题:为什么将客户端的部分IP地址附加到上面的字符串?
额外信息:
当我一起删除这一行时,问题似乎消失了:
snprintf(iip, 15, "%s", inet_ntoa(cli_addr.sin_addr));
但我不想删除该行。
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <err.h>
#include <string.h>
char * nnn;
char iii [500];
char ii2 [3];
char iip [15];
int main()
{
int one = 1, client_fd;
struct sockaddr_in svr_addr, cli_addr;
socklen_t sin_len = sizeof(cli_addr);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
err(1, "can't open socket");
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
int port = 86;
svr_addr.sin_family = AF_INET;
svr_addr.sin_addr.s_addr = INADDR_ANY;
svr_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) {
close(sock);
err(1, "Can't bind");
}
listen(sock, 5);
while (1) {
client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
snprintf(iip, 15, "%s", inet_ntoa(cli_addr.sin_addr));
ssize_t t = read(client_fd,iii,500);
if ( t > 0 ) { iii[ t ] = '\0'; ii2[ t ] = '\0'; }
strncpy(ii2, iii + 5, 3);
printf(ii2);
printf("---");
printf("\n");
asprintf(&nnn, "%s\n", ii2);
write(client_fd, nnn, strlen(nnn));
close(client_fd);
}
}
答案 0 :(得分:3)
您错误地使用了strncpy
。此功能设计用于固定长度的字符串 - 这些日子很少使用。
该函数将三个字符复制到ii2
,但它不会添加空终止符。通过拨打memcpy
来取代通话,并在最后一个字符中设置'\0'
,如下所示:
char ii2 [4]; // <<== 3 plus 1 for '\0'
...
memcpy(ii2, iii + 5, 3);
ii2[3] = '\0';
请注意,如果您只需要从可能更长的字符串中打印三个字符,则不需要ii2
。您可以使用%.3s
格式说明符,如下所示:
asprintf(&nnn, "%.3s\n", iii+5);
您需要调用free(nnn)
以避免造成内存泄漏。此外,由于结果的大小限制为5,因此您可以将asprintf
调用sprintf
替换为固定大小的缓冲区。
答案 1 :(得分:2)
添加到dasblinkenlight的答案。
char ii2 [3];
ssize_t t = read(client_fd,iii,500);
if ( t > 0 ) { iii[ t ] = '\0'; ii2[ t ] = '\0'; }
这看起来像SegFault
的食谱。尝试将值存储在远远超出ii2
数组大小的位置。 (最坏情况:t = 500)
答案 2 :(得分:1)
尝试将char iip [15];
大小增加到16.对于初学者来说忘记保留'\0'
字符空间的常见问题。 char ii2 [3];
也太短,无法存储长度为3的字符串,所以我建议将空间增加到4。