我正在尝试在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]
PS:我使用的是Ubuntu 12.04,我实际上编写了这些程序并成功执行了这些程序。但我最近迁移到Linux Mint 13 Cinnamon。我重新编译了程序。可能他们也成功地在薄荷上执行了。但现在它似乎以某种方式抓住了这个错误。
如果您在 64 位系统上运行,您的呼叫;
printf("Server received connections from %s n",
(char *)inet_ntoa(cli_addr.sin_addr));
。可能会破裂。由于您没有包含<arpa/inet.h>
,因此您没有inet_ntoa的定义。这将使编译器假定它返回一个int
。由于int
不一定是 64 位(实际上大多数机器似乎不是),因此它不够长,无法存储返回的 char 指针,因此 printf 会崩溃并显示无效字符串。这发生在(例如)64位MacOS X上。
只需简单地将#include <arpa/inet.h>
放在服务器中的包含中即可解决此问题。
您也不应该忽视int
和socklen_t
之间的差异,并解决混淆cli_size
和serv_size
的问题,阅读已经存在的评论和答案以获取更多信息。
我会说问题是缺少inet_ntoa()
的原型。
这让编译器假设它返回int
.
这使得以下行使应用程序崩溃:
printf("Server received connections from %s n", (char *)inet_ntoa(cli_addr.sin_addr));
包含<arpa/inet.h>
以下代码后,即使使用-Wall
,他们也毫无警告地编译了.
printf("Server received connections from %s n", inet_ntoa(cli_addr.sin_addr));