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]

PS:私はUbuntu 12.04を使用していて、実際にこれらのプログラムを作成して、プログラムを正常に実行しました。しかし、私は最近Linux Mint13Cinnamonに移行しました。プログラムを再コンパイルしました。おそらく彼らはミントでもうまく実行されました。しかし、今ではどういうわけかこのバグを捕らえたようです。

4

2 に答える 2

5

64ビットシステムで実行している場合は、呼び出し。

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

...壊れることがあります。を含め<arpa/inet.h>ていないため、inet_ntoaの定義はありません。これにより、コンパイラは.を返すと想定しますintintは必ずしも64ビットではないため(実際にはほとんどのマシンではそうではないようです)、返されるcharポインターを格納するのに十分な長さではないため、printfは無効な文字列でクラッシュします。これは、(たとえば)64ビットのMacOSXで発生します。

サーバーのインクルードに単純に入れるだけ#include <arpa/inet.h>で、その問題は解決します。

また、との違いを無視してはならずintsocklen_tとの混同の問題を修正し、既存のコメントと回答を読んで詳細を確認してくださいcli_sizeserv_size

于 2012-10-25T12:15:44.933 に答える
1

問題はのプロトタイプがないことだと思います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));
于 2012-10-25T12:13:58.863 に答える