c - 使用 C (Ubuntu) 的套接字编程中的段错误

标签 c sockets ubuntu segmentation-fault coredump

我正在编写一个 C 程序,它创建一个服务器端程序,将消息“从服务器”发送到客户端程序。但是,我对客户有疑问。 strcpy(hostname,argv[1]); 行上的错误段错误(核心转储)(我已在客户端代码上标记)。 以下是我的代码: 服务器:

/* Server program */    
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>


int main(int argc, char* argv[])
{
        /* Declaration of sock and newsock as integer variables to handle       the socket */
        int newsock,sock;

        /* Declaration of ptr to store info about the host */
        struct hostent* ptr;

        /* Declaration of address as sockaddr_in structure to store info    about Internet domain socket address */
        struct sockaddr_in address;

        /* Declaration of addrlen as integer to store the address length in         internet domain */
        int addrlen=sizeof(struct sockaddr_in);

        /* Declaration of buf as string to handle the message */
        char buf[100];

        /* Declaration of msg as string to store the message to be sent */
        char msg[50] ={"From server"};

        /* Declaration of portnum as integer to store port number */
        int portnum;

        /* Declaration of qsize as integer to store queue size */
        int qsize = 5;

        /* Store port number from the command line argument */
        portnum= atoi(argv[1]);

        /* Create a socket */
        printf("Creating socket");
        sock=socket(AF_INET,SOCK_STREAM,0);
        if(sock == -1)
        {
            printf("\nCannot create a socket\n");
            return 0;
        }

        /* Store the values in the address structure */
        address.sin_addr.s_addr=INADDR_ANY;
        address.sin_port=htons(portnum);
        address.sin_family=AF_INET;

        /* Binding to local address */
        printf("\nBinding to port\n");
        if(bind(sock,(struct sockaddr*)&address,sizeof(address))== -1)
        {
            printf("\nCannot connect to host\n");
            return 0;
        }

        /* Get local socket address */
        getsockname(sock,(struct sockaddr*)&address,(socklen_t*)&addrlen);
        printf("Opened socket:%d\nport:% d\n",sock, ntohs(address.sin_port));
        printf("Server\n sin_family = %d\n sin_addr.s_addr = %d\n sin_port = %d\n",address.sin_family, address.sin_addr.s_addr, ntohs(address.sin_port));

        /* Create a queue */
        printf("Queue size %d:",qsize);
        if(listen(sock,qsize) == -1)
        {
            printf("\nCannot listen\n");
            return 0;
        }

    for(;;)
        {
            printf("\nWaiting for a connection\n");
            /* Get the connected socket and accept the connection */
            newsock=accept(sock,(struct sockaddr*)&address,(socklen_t*)&addrlen);
            printf("\nGot a connection");

            /* Send the message to the client */
            strcpy(buf,msg);
            printf("\nMessage sent to client:%s",buf);
            write(newsock,buf,strlen(buf)+1);

            /* Read read the message from the client */
            read(newsock,buf,100);
            printf("\nMessage received from client:%s",buf);

            /* Terminate the connection */
            if(close(newsock) == -1)
                {
                printf("\nCould not close socket\n");
                return 0;
            }
        }
}

客户:

    /* Client program */

        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <netdb.h>
        #include <string.h>
        #include <unistd.h>
        #include <stdio.h>

        int main(int argc, char* argv[])
        {
            /* Declaration of sock as integer variable to handle the socket */
            int sock;

            /* Declaration of ptr to store info about the host*/    
            struct hostent* ptr;

            /* Declaration of address as sockaddr_in structure to store info    about Internet domain socket address */
            struct sockaddr_in address;

            /* Declaration of hostaddr as long to store the host address */
            long hostaddr;

            /* Declaration of buf and buf1 as string variables to handle the    message */  
            char buf[100],buf1[100];

            /* Declaration of amount as unsigned variable to store the number of        bytes returned by read system call      */
            unsigned amount;

            /* Declaration of hostname as string variable to store host name */
            char hostname[255];  

            /* Declaration of portnum as integer to store port number */
            int hostport;

            /* Get the host name and port number from the command line arguments        */
FAULT==================>   strcpy(hostname,argv[1]);
            hostport=atoi(argv[2]);

            /* Create a socket */
            printf("Making a socket");
            sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(sock == -1)
            {
                printf("\nCannot make a socket\n");
                return 0;
            }

            /* Get IP address from host name */
            ptr=gethostbyname(hostname);

            /* Copy address into long */
            memcpy(&hostaddr,ptr->h_addr,ptr->h_length);

            /* Store the values in the address structure */
            address.sin_addr.s_addr=hostaddr;
            address.sin_port=htons(hostport);
            address.sin_family=AF_INET;

            /* Connect to the server */
            printf("\nConnecting to %s on port %d",hostname,hostport);
            if(connect(sock,(struct sockaddr*)&address,sizeof(address)) == -1)
            {
                printf("\nCould not connect to host\n");
                return 0;
            }

            /* Read the message from the server */
            amount=read(sock,buf,100);
            printf("\nMessage received from server:%s",buf);

            /* Write the message to the server */
            strcpy(buf1,"From client");
            write(sock,buf1,amount);
            printf("\nMessage sent to server:%s",buf1);

            /* Terminate the connection */
            printf("\nClosing socket\n");
            if(close(sock) == -1)
            {
                printf("\nCould not close socket\n");
                return 0;
            }
        }

以下是使用 gdb 的调试 session :

pc03@pc03:~$ cc sockc.c
pc03@pc03:~$ ./a.out localhost.localdomain 58733
Segmentation fault
pc03@pc03:~$ cc -g sockc.c
pc03@pc03:~$ ./a.out localhost.localdomain 58733
Segmentation fault
pc03@pc03:~$ gdb ./a.out
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/pc03/a.out...done.
(gdb) run
Starting program: /home/pc03/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x001a1210 in strcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb) backtrace
#0  0x001a1210 in strcpy () from /lib/tls/i686/cmov/libc.so.6
#1  0x080486bf in main (argc=1, argv=0xbffff514) at sockc.c:38
(gdb) frame 1
#1  0x080486bf in main (argc=1, argv=0xbffff514) at sockc.c:38
38      strcpy(hostname,argv[1]);
(gdb) print hostname
$1 = "\277\022\000 \300\022\000\000\000\000\000\364\277\022\000\257\242\021\000\000\260\022\000\000\020\000\000\001\000\000\000\364\277\022\000\000\000\000\000X\363\377\277\177\246\021\000\260\312\022\000\230\375\377\267\001\000\000\000\001\000\000\000\000\000\000\000\240\362\377\277\364\277\022\000\000\000\000\000\000\000\000\000\060\363\377\277\200U\022\000\241\225\022\000|\212\022\000$\305\022\000\000\000\000\000\224\004\021\000\060\363\377\277\022\006\021\000P\363\377\277\324\002\021\000\002\000\000\000\064\003\021\000\a\000\000\000\220\246\023\000\020ii\rP\363\377\277\266\212\021\000\311\a\024\000\275\203\004\b\000\000\000\000$\203\004\bH\373\377\267\002\000\377\277 \346\021\000$\203\004\b\340\313\022\000\364\277\022\000\250\033\023\000\001\000\000\000\334\363\377\277f\220\021\000\200\364\377\277,1\021\000$\305\022\000\260\312\022", '\000' <repeats 21 times>"\260, \035\023\000܈\022"
(gdb) print argv
$2 = (char **) 0xbffff514

感谢您的帮助!

最佳答案

正如您最后的 gdb 输出所示,问题出在以下语句中: memcpy(&hostaddr,ptr->h_addr,ptr->h_length);。很容易猜到ptrNULL

ptr=gethostbyname(hostname); 是问题的根源。如果 hostname 未解析,ptr 将为 NULL,然后您将遇到段错误。您应该始终检查函数的返回值。

关于c - 使用 C (Ubuntu) 的套接字编程中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26595218/

相关文章:

javascript - Java Server Socket 传输 String 到 web socket

laravel - 将 Laravel 从 vagrant 连接到主机 MSSQL express

c - 整数乘积溢出

sockets - Lua Socket Lib问题

ruby-on-rails - 将多个 Rails 应用程序部署到 DigitalOcean

ruby - 在 ubuntu 上安装 ruby​​ 要求

linux - GitHub SSH 访问无效

c - 从文件句柄获取真实路径

c - 为什么要在堆上而不是栈上分配内存?

c - 为什么mov指令不能正确执行?