C-SERVER-在以下位置的奇怪行为:strncpy(ii2,iii+;5,3);

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

让我们向C-SERVER发送一条消息:

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'; }