c - 段错误问题

标签 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.

我不明白为什么我在服务器中收到此错误:段错误(核心转储)

这是我的代码:

客户:

#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();
    }

  }

}

最佳答案

您的服务器代码似乎缺少原型(prototype) 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]

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

关于c - 段错误问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22450785/

相关文章:

http - 符合 HTTP 1.1 服务器和客户端连接半关闭

c - 如何使用 Union 在 1 个 C 数组中存储 2 个不同的结构

c - 在哪里可以找到 PDF 格式的 C89/C90 标准?

java - 使用纯 Java 与 SSH 服务器通信以进行文件访问

c# - 使用 C# 套接字发现 Lantronix XPort Pro 和 XPort

java - 为什么我的套接字 getInputStream 返回 null?

c - 主机到网络双重?

c - 如何让 do while 循环结束时的 printf 被执行?它只是跳过它

c - 了解指针数组语法

c - malloc 可以分配的最大内存