C-SERVER-在以下位置的奇怪行为:strncpy(ii2,iii+;5,3);
让我们向C-SERVER发送一条消息:C-SERVER-在以下位置的奇怪行为:strncpy(ii2,iii+;5,3);,c,C,让我们向C-SERVER发送一条消息: echo '1234567890' | nc <ip> <port> 但我只要求它从收到的消息中打印3个字符。 (从第五个字符开始) 它只能打印:(加上--) 问题:为什么要将客户端的部分IP地址附加到上面的字符串 额外信息: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h&g
echo '1234567890' | nc <ip> <port>
但我只要求它从收到的消息中打印3个字符。(从第五个字符开始) 它只能打印:(加上--) 问题:为什么要将客户端的部分IP地址附加到上面的字符串 额外信息:
#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);
}
}
当我一起删除这一行时,问题似乎消失了:
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);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
char*nnn;
char iii[500];
char-ii2[3];
char-iip[15];
int main()
{
int one=1,客户端\u fd;
svr\u addr、cli\u addr中的结构sockaddr\u;
socklen\u t sin\u len=sizeof(cli\u addr);
intsock=socket(AF_INET,sock_STREAM,0);
if(sock<0)
错误(1,“无法打开插座”);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(int));
int端口=86;
svr\u addr.sin\u family=AF\u 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){
关闭(袜子);
错误(1,“无法绑定”);
}
听(短袜,5);
而(1){
client\u fd=accept(sock,(struct sockaddr*)&cli\u addr和sin\u len);
snprintf(iip,15,“%s”,inet_ntoa(cli_addr.sin_addr));
ssize_t=读取(客户端fd,iii,500);
如果(t>0){iii[t]='\0';ii2[t]='\0';}
strncpy(ii2,iii+5,3);
printf(ii2);
printf(“--”)号;
printf(“\n”);
asprintf(&nnn,“%s\n”,ii2);
写(客户机,nnn,strlen(nnn));
关闭(客户_fd);
}
}
尝试增加字符iip[15]代码>大小为16。beginers忘记为'\0'
字符保留空间是常见的问题<代码>字符ii2[3]
也太短,无法存储长度为3的字符串,因此我建议将房间增加到4。您使用的strncpy不正确。这个函数是为固定长度字符串设计的,这是现在很少使用的
该函数将三个字符复制到ii2
,但不添加空终止符。将调用替换为对memcpy
的调用,并在最后一个字符中设置'\0'
,如下所示:
char ii2 [4]; // <<== 3 plus 1 for '\0'
...
memcpy(ii2, iii + 5, 3);
ii2[3] = '\0';
asprintf(&nnn, "%.3s\n", iii+5);
您需要调用free(nnn)
以避免造成内存泄漏。此外,由于结果的大小限制为5,您可以将asprintf
调用替换为sprintf
到固定大小的缓冲区。添加到的答案
char ii2 [3];
ssize_t t = read(client_fd,iii,500);
if ( t > 0 ) { iii[ t ] = '\0'; ii2[ t ] = '\0'; }
这看起来像是SegFault
的配方。试图将值存储在远远超出ii2
数组大小的位置。(最坏情况:t=500)当你复制到iii2
@某个程序员的时候,你忘了需要字符串终止符,你能告诉我怎么做吗?首先,对于一个包含三个字符的字符串,由于终止符的存在,您需要一个包含四个字符的数组。其次,strncpy
可能不会添加终止符,因此必须显式地添加终止符(例如,ii2[3]='\0'
)。与您的问题无关,请停止使用全局变量,并尝试提出一些描述性变量名称。及早养成好习惯对你以后会有所帮助。我不确定ii2的意义是什么,但几乎可以肯定它应该是一个局部变量。但是,如果唯一的原因是打印3个字符,从iii
的第六个字符开始,则不需要变量和副本:printf(“%.3s”,iii+5)
就可以了。ii2
也太短而且被误用了(strncpy
没有把它变成C字符串)。@chqrlie谢谢你的评论!
asprintf(&nnn, "%.3s\n", iii+5);
char ii2 [3];
ssize_t t = read(client_fd,iii,500);
if ( t > 0 ) { iii[ t ] = '\0'; ii2[ t ] = '\0'; }