我正在编写一个 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);
。很容易猜到ptr
是NULL
。
ptr=gethostbyname(hostname);
是问题的根源。如果 hostname
未解析,ptr
将为 NULL
,然后您将遇到段错误。您应该始终检查函数的返回值。
关于c - 使用 C (Ubuntu) 的套接字编程中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26595218/