2012-10-25 68 views
0

我试图写C.一个简单的服务器 - 客户端通信程序但作为一个客户端试图连接到服务器,我不断尽快获得服务器端错误:分段错误

分割故障

服务器端代码:

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

void error(char *); 

int main(int argc, char *argv[]) 
{ 
int sockfd, newsockfd, n, serv_size, cli_size, port_no, bindfd, readfd, writefd, listenfd; 
char sbuffer[256]; 
char *p; 
p = &sbuffer[0];  

struct sockaddr_in serv_addr, cli_addr; 

if (argc < 2) 
    error("No port no. Specified!\n"); 

//creating sever side socket  
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd == -1) 
    error("Server side listening Socket could not be created!\n"); 


bzero((char *)&serv_addr, sizeof(serv_addr)); 
port_no = atoi(argv[1]); 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(port_no); 
serv_addr.sin_addr.s_addr = INADDR_ANY; 

//binding socket 
bindfd = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 
if (bindfd == -1) 
    error("Failed to bind server side socket!\n"); 

//listening for incoming connections 
listenfd = listen(sockfd, 5); 
if (listenfd == -1) 
    error("Failed to lisen to incoming connections!\n"); 

serv_size = sizeof(serv_addr); 
cli_size = sizeof(cli_addr); 
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &serv_size); 
if (newsockfd == -1) 
    error("Failed to accept connections from client!\n"); 

printf("Server received connections from %s \n", (char *)inet_ntoa(cli_addr.sin_addr));  
while(1) 
{ 
    bzero(p, sizeof(sbuffer)); 
    readfd = read(newsockfd, p, sizeof(sbuffer)); 
    if (readfd == -1) 
     error("Sorry. Unable to read message from client!\n"); 
    printf("Message Received: "); 
    puts(sbuffer); 

    bzero(p, sizeof(sbuffer)); 
    printf("\nEnter Your Message for client: "); 
    gets(sbuffer); 
    writefd = write(newsockfd, p, sizeof(sbuffer)); 
    if (writefd == -1) 
     error("Sorry. Message Could not be sent to client.\n"); 
    printf("Congratulations! Message has been sent to client.\n"); 
}  

return 0; 
} 
void error(char *msg) 
{ 
perror(msg); 
exit(1); 
} 

客户端代码:

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

void error(char *); 
int main(int argc, char *argv[]) 
{ 
int sockfd, newsockfd, port_no, n, connectfd, readfd, writefd; 
char cbuffer[256]; 
char *ptr = &cbuffer[0]; 

struct sockaddr_in serv_addr; 
struct hostent *he; 

if (argc != 3) 
    error("Incomplete arguments!\n"); 

port_no = atoi(argv[2]); 
he = gethostbyname(argv[1]); 
if (he == NULL) 
    error("No Such Host!\n"); 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if(sockfd == -1) 
    error("Sorry. Socket could not be created!\n"); 

bzero((char *)&serv_addr, sizeof(serv_addr)); 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(port_no); 
serv_addr.sin_addr = *((struct in_addr *)he->h_addr); 

connectfd = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 
if (connectfd == -1) 
    error("Sorry. Could not connect to server.\n"); 

while(1) 
{ 
    bzero(ptr, sizeof(cbuffer)); 
    printf("\nEnter message for Server: \n"); 
    gets(cbuffer); 
    writefd = write(sockfd, ptr, sizeof(cbuffer)); 
    if (writefd == -1) 
     error("Sorry. Could not send message to Server."); 

    printf("Congratulations! Server Successfully Received your message.\n");  

    bzero(ptr, sizeof(cbuffer)); 
    readfd = read(sockfd, ptr, sizeof(cbuffer)); 
    if (readfd == -1) 
     error("Sorry. Message from server could not be read.\n"); 

    printf("Message Received: "); 
    puts(cbuffer); 
} 
return 0; 
} 
void error(char *msg) 
{ 
perror(msg); 
exit(1); 
} 

这是在编译serv.c我的编译时警告:

cc -o s serv.c 
serv.c: In function ‘main’: 
serv.c:47:52: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 

附: :我使用的是Ubuntu 12.04,我实际上编写了这些程序并成功执行了这些程序。但我最近迁移到Linux薄荷13肉桂。我重新编译了这些程序。也许他们也成功地在造币厂执行。但现在似乎已经以某种方式发现了这个bug。

+2

请尽量不要浪费别人的时间。目前代码没有正确缩进,使阅读变得困难。同样根据我的经验,无论如何,正确缩进代码都是很好的工程实践,自己做这件事可能会暴露出您正在寻求解决的问题。 对于自己的帮助,在read()和这样的调用之后,还打印出errno值。有像EAGAIN这些值其实不是错误。在此之后,作为已经暗示的下面,请调试器,并找出它崩溃的原因以及为什么。 –

+1

http://www.cs.cmu.edu/~gilpin/tutorial/ – Jeyaram

+0

尝试使用getaddrinfo()的新方法,而不是手动填充serv_addr结构体。另一个优点是getaddrinfo()支持IPv6。 – codewarrior

回答

4

如果您在64位系统上运行,您的呼叫;

printf("Server received connections from %s \n", 
    (char *)inet_ntoa(cli_addr.sin_addr));  

...可能会中断。由于您没有包含<arpa/inet.h>,因此您没有inet_ntoa的定义。这将使编译器假定它返回一个int。由于int不一定是64位(实际上似乎不是大多数机器),所以存储返回的字符指针的时间不够长,所以printf会导致无效字符串崩溃。发生这种情况(例如)64位的MacOS X.

只是简单地把#include <arpa/inet.h>包括在服务器之间将解决这个问题。

你也应该不能忽视intsocklen_t之间的区别和修复混合起来cli_sizeserv_size的问题,阅读已经存在的意见和答案,如果要了解他们。

+0

谢谢! '#include '立即修复了警告和分段错误。 –

+0

socklen_t和int有什么区别? socklen_t的目的是什么? –

+0

@IndradhanushGupta'socklen_t'总是无符号的,至少有32位。由于int是有符号的,并且在C中可能只有16位,因此'socklen_t'作为单独的数据类型引入以覆盖所有情况。 –

0

我想说这个问题是inet_ntoa()缺失的原型。

这让我们编译器假定它返回int

这让下面的行崩溃的应用程序:

printf("Server received connections from %s \n", (char *)inet_ntoa(cli_addr.sin_addr));  

已经包含<arpa/inet.h>的follwing代码已经对子级不与-Wall甚至警告编译。

printf("Server received connections from %s \n", inet_ntoa(cli_addr.sin_addr));