分段故障问题

时间:2014-03-17 09:34:29

标签: c sockets

我有这个项目要为学校做,我被卡住了。

编写使用TCP套接字进行通信的客户端 - 服务器应用程序。客户端向服务器发送一个短语,服务器使用接收到的字符串中的空格字符数进行应答。服务器返回二进制格式的整数N(带符号),以4个字节表示,具有以下含义:

    N >= 0 – the number of space characters in the received string;
    N = -1 – error receiving the string, or the client does not respect the protocol;
    N = -2 – if the count of spaces cannot be represented on 4 bytes (with sign) (i.e. greater that 231 -1). On 4 bytes the range of signed numbers that can be represented is -231 … +231-1.

我无法弄清楚为什么我在服务器中收到此错误:Segmentation fault(core dumped)

这是我的代码:

客户端:

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

#define max 100

int main() {
  int c, cod;
  int32_t r;
  struct sockaddr_in server;
  char s[max];

  c = socket(PF_INET, SOCK_STREAM, 0);
  if (c < 0) {
    fprintf(stderr, "Error creating socket client.\n");
    return 1;
  }

  memset(&server, 0, sizeof(struct sockaddr_in));
  server.sin_family = AF_INET;
  server.sin_port = htons(4321);
  server.sin_addr.s_addr = inet_addr("127.0.0.1");

  cod = connect(c, (struct sockaddr *) &server, sizeof(struct sockaddr_in));
  if (cod < 0) {
    fprintf(stderr, "Error connecting to server.\n");
    return 1;
  }

  printf("Please insert a string to be sent: ");
  fgets(s, max, stdin);


  cod = send(c, s, strlen(s) + 1, 0);
  if (cod != strlen(s) + 1) {
    fprintf(stderr, "Error sending data to server.\n");
    return 1;
  }

  cod = recv(c, &r, sizeof(int32_t), MSG_WAITALL);
  r = ntohl(r);
  if (cod != sizeof(int)) {
    fprintf(stderr, "Error receiving data from server.\n");
    return 1;
  }

  printf("Server returned %d space characters in the sent string.\n", r);

  close(c);
}

服务器:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int c;

void time_out(int semnal) {
  int32_t r = -1;
  r = htonl(r);
  printf("Time out.\n");
  send(c, &r, sizeof(int32_t), 0);
  close(c); 
  exit(1);
}

void tratare() {
  int cod;
  int32_t r;
  uint8_t b;
  struct sockaddr_in server;

  if (c < 0) {
    fprintf(stderr, "Error connecting with the client.\n");
    exit(1);
  }
  else
    printf("A new client connected.\n");

  signal(SIGALRM, time_out);
  alarm(10);

  r = 0; 
  do {
    cod = recv(c, &b, 1, 0);
    printf("I received %d characters.\n", cod);

    if (cod == 1) 
      alarm(10);  

    if (cod != 1) {
      r = -1;
      break;
    }

    if (b == ' ') {

      if (r == INT32_MAX) { 
        r = -2;
        break;
      }
      r++;
    }
  }
  while (b != 0); 
  alarm(0); 

  r = htonl(r);
  send(c, &r, sizeof(int32_t), 0);
  r = ntohl(r);

  close(c);

  if (r >= 0)
    printf("Connection closed. Sent %d spaces.\n", r);
  else {
    printf("Connection closed. Error code %d.\n", r);
    exit(1);
  }

  exit(0);
  }


int main() {
  int s, l, cod;
  struct sockaddr_in client, server;  

  s = socket(PF_INET, SOCK_STREAM, 0);
  if (s < 0) {
    fprintf(stderr, "Error creating the socket server.\n");
    return 1;
  }

  memset(&server, 0, sizeof(struct sockaddr_in));
  server.sin_family = AF_INET;
  server.sin_port = htons(4321);
  server.sin_addr.s_addr = INADDR_ANY;

  cod = bind(s, (struct sockaddr *) &server, sizeof(struct sockaddr_in));
  if (cod < 0) {
    fprintf(stderr, "Error on bind. Port is already used.\n");
    return 1;
  }

  listen(s, 5);

  while (1) { 

    memset(&client, 0, sizeof(client));
    l = sizeof(client);

    printf("Waiting for a client to connect.\n");
    c = accept(s, (struct sockaddr *) &client, &l);
    printf("Client connected with address %s and port %d.\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

    if (fork() == 0) { 
      tratare();
    }

  }

}

1 个答案:

答案 0 :(得分:1)

原型inet_ntoa()似乎缺少服务器的代码,因此编译器将int视为返回值,它应使用char*,至少在64位系统上是致命的int为32位宽,char*为64位宽,因此inet_ntoa()返回的指针将其一半的位切断。

要解决此问题,请添加:

#include <arpa/inet.h>

在编译服务器的源代码时,预计会发出这样的警告:

 warning: implicit declaration of function ‘inet_ntoa’ [-Wimplicit-function-declaration]

如果是这种情况,这里吸取的教训是:始终严肃对待警告!