【问题标题】:socket client don't work on Kali套接字客户端在 Kali 上不起作用
【发布时间】:2016-10-21 20:46:51
【问题描述】:

我正在尝试制作一个简单的客户端-服务器程序,但客户端总是出现分段错误。我检查了 IP 地址、端口,尝试了许多替代解决方案,但对我不起作用。

服务器代码:

    #include <arpa/inet.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    int main(int argc, char const *argv[])
    {
        int sock,mysock;
        struct sockaddr_in server;
        char buff[1024];

     char s[256];

    if (!gethostname(s, sizeof s))
        {
            printf ("Machine: %s\n", s);
            {
                struct hostent *host= gethostbyname(s);

                if (host  != NULL)
                {
                    struct in_addr **adr;

                    for (adr = (struct in_addr **)host->h_addr_list; *adr; adr++)
                    {
                        printf("IP : %s\n", inet_ntoa(**adr));
                    }
                }
            }
        } 


        /*creation du socket*/
        sock=socket(AF_INET,SOCK_STREAM,0);
        if (sock<0)
        {
            perror("creation de socket echouer\n");
            exit(1);
        }
        server.sin_family=AF_INET;
        server.sin_addr.s_addr=INADDR_ANY;
        server.sin_port=5000;

        if (bind(sock, (struct sockaddr *) &server,sizeof(server)) < 0) 
             {perror("ERROR on binding");
              exit(1);}

        /*listen for just 1 connection*/
        listen(sock,1);
        mysock=accept(sock,(struct sockaddr *)0,0);
        if (mysock==-1)
        {
            perror("accept failed");
            exit(1);
        }




        write(mysock,"you are connected to: my server\n",55);
        read(mysock,buff,sizeof(buff));
        printf("%s\n",buff);
        gets();
        close(sock);
        close(mysock);


        return 0;
    }

客户端代码:

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char const *argv[])
{
    int sock;
    struct sockaddr_in server;
    struct hostent *hp;
    char buff[1024];

    /*creation du socket*/
    sock=socket(AF_INET,SOCK_STREAM,0);
    if (sock<0)
    {
        perror("creation de socket echouer\n");
        exit(1);
    }
    server.sin_family=AF_INET;
    hp = gethostbyname(argv[1]);
    if (hp == NULL) {
        perror("ERROR, no such host\n");
        exit(0);
    }
    printf("0\n");
    server.sin_addr.s_addr=inet_addr("127.0.1.1");
    server.sin_port=htons(5000);
printf("1\n" );
    if (connect(sock,(struct sockaddr *)&server,sizeof(server)<0))
    {
        perror("connection failed");
        exit(1);
    }printf("2\n");
    read(sock,buff,sizeof(buff));
    printf("%s\n",buff);
    write(sock,"thanks for accepting me\n",25);

    system("PAUSE");
    close(sock);
    return 0;
 }

【问题讨论】:

  • 您是否正在向您的程序传递参数。
  • 使用参数运行程序。它将开始显示错误
  • SO 不是调试服务。使用符号编译,在调试器中运行代码以逐行跟踪程序,检查相关变量的值以了解实际情况。如果出现具体问题,请随时返回此处。

标签: c sockets segmentation-fault client-server


【解决方案1】:

似乎由于这条线,您在客户端遇到了分段错误:

hp = gethostbyname(argv[1]);

这里获取segfault的方法是传递一个NULL-pointer。因此,您每次在没有命令行参数的情况下运行客户端时都会这样做。
附言不太明白,你为什么需要它。


注意事项:

  • 如果能修正明显的失误,例如斯蒂芬提到。还要像这样初始化缓冲区:char buff[1024] = {0}; 以避免麻烦。并检查函数的返回值是否发生错误。
  • 来自man

gethostbyname*() 和 gethostbyaddr*() 函数已过时。 应用程序应改为使用 getaddrinfo(3) 和 getnameinfo(3)。


编辑: 所以你的客户的工作代码可以是这样的:

int main(int argc, char const *argv[]) {
    int sock;
    ssize_t bytes;
    struct sockaddr_in server;
    char buff[1024] = {0}, tosend[] = "thanks for accepting me";
    /*
    struct hostent *hp;
    if(argv[1]) {
        hp = gethostbyname(argv[1]);
        if (hp == NULL) {
            perror("gethostbyname");
            return;
        }
        // something with hp
    }
   */
    /*creation du socket*/
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        exit(1);
    }
    memset(&server, 0, sizeof (struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.1.1");
    server.sin_port = htons(5000);
    printf("1\n");
    if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0) {
        perror("connect");
        exit(1);
    }
    printf("2\n");
    if ((bytes = read(sock, buff, sizeof(buff) - 1)) < 0) {
        perror("read");
        exit(1);
    } else if (! bytes)
        puts("finished");
      else
        printf("%s\n", buff);
    if (write(sock, tosend, sizeof tosend) < 0)
        perror("write");

    return 0;
 }

如果您使用注释行,请在运行客户端时传递一些命令行参数,例如./client somename

ALSO 在服务器端,您至少应该更改以下内容:

  • 删除或更改gets() 调用,因为它需要一个参数
  • 设置端口号如htons(5000)

【讨论】:

  • 获取段错误的另一种方法是访问argv 数组中不存在的元素。您不需要初始化网络缓冲区。
  • @EJP 也许,但不确定。我不能以这种方式引发段错误。至于缓冲区。在某些情况下,未初始化的缓冲区指向堆栈上前一个函数留下的垃圾。因此,如果现在它指向例如到 "AAAAAA\0" 并且你从像 "BBB" 这样的服务器读取 3 个字节,我们可以得到像 "BBBAAA\0" 这样的字符串。所以我说初始化缓冲区会很好。
  • 请问有人可以更正我的代码并发布吗?
【解决方案2】:

可能还有更多问题,但这绝对是错误的:

your code:   if (connect(sock,(struct sockaddr *)&server,sizeof(server)<0))
correct:     if (connect(sock,(struct sockaddr *)&server,sizeof(server))<0)
                                                                       ^^^^

【讨论】:

  • 嗨,谢谢,我注意到发布后问题是无法连接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 2014-12-11
  • 1970-01-01
  • 2010-11-21
  • 2015-03-23
  • 2016-12-27
相关资源
最近更新 更多