Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 发送和接收不一致_C_Sockets_Tcp - Fatal编程技术网

C 发送和接收不一致

C 发送和接收不一致,c,sockets,tcp,C,Sockets,Tcp,好了,伙计们,我已经连续工作了两天,搜索bug,寻找去年的解决方案和其他软件,但都找到了 我的问题是,我需要编写一个相当简单的服务器-客户机应用程序,在这个应用程序中,响应和回复都可以。我写了一些小程序来演示我的问题 在您抱怨send和recv不完整之前,要检查的内容不应小于0。我知道我得检查一下 h只是所有输入和静态变量的标题 // guard block: #ifndef COMMON_H #define COMMON_H // default hostname and port: #de

好了,伙计们,我已经连续工作了两天,搜索bug,寻找去年的解决方案和其他软件,但都找到了

我的问题是,我需要编写一个相当简单的服务器-客户机应用程序,在这个应用程序中,响应和回复都可以。我写了一些小程序来演示我的问题

在您抱怨send和recv不完整之前,要检查的内容不应小于0。我知道我得检查一下

h只是所有输入和静态变量的标题

// guard block:
#ifndef COMMON_H
#define COMMON_H

// default hostname and port:
#define DEFAULT_HOST    "localhost"
#define DEFAULT_PORT    "1280"

#include <stdarg.h>
#include <ctype.h> 

// IO, C standard library, POSIX API, data types:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>

// Sockets, TCP, ... :
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <fcntl.h>

// Assertions, errors, signals:
#include <assert.h>
#include <errno.h>
#include <signal.h>

static struct addrinfo *ai = NULL;      // stores address information
static int sockfd = -1;                 // socket file descriptor
static int connfd = -1;                 // connection file descriptor

void terminate(int sig);
void init_signal_handler(void);
void free_ressources(void);
void error(char* format, ...);

void terminate(int sig) {
  error("Caught signal %d. Terminating...\n",sig);
}

void init_signal_handler(void) {
  struct sigaction sa;
  sa.sa_handler = terminate;
  if (-1 == sigemptyset(&(sa.sa_mask))) {
    error("sigemptyset()");
  }
  if (-1 == sigaction(SIGINT, &sa, NULL)) {
    error("sigaction()");
  }
  if (-1 == sigaction(SIGTERM, &sa, NULL)) {
    error("sigaction()");
  }
}

void error(char *format, ...) {
  va_list arg;

  va_start (arg, format);
  (void) vfprintf (stderr, format, arg);
  va_end (arg);

  free_ressources();

  exit(EXIT_FAILURE);
}

void free_ressources(void) {
  (void) printf("Freeing all ressources...\n");
  if(sockfd != -1) close(sockfd);
  if(connfd != -1) close(connfd);
  freeaddrinfo(ai);
}
#endif // COMMON_H
来自客户端的输出

Sending message 0XF0F0
Recieved from Server 0
Sending message 0XF0F1
Recieved from Server 0
Sending message 0XF0F2
Recieved from Server 0
Sending message 0XF0F3
Recieved from Server 0
Sending message 0XF0F4
Recieved from Server 0
Sending message 0XF0F5
Recieved from Server 0
Sending message 0XF0F6
Recieved from Server 0
Sending message 0XF0F7
Recieved from Server 0
Sending message 0XF0F8
Recieved from Server 0
Sending message 0XF0F9
Recieved from Server 0
Freeing all ressources...
总之,我知道这可能是一个愚蠢而简单的问题,但为什么会是这样呢?为什么服务器在发送第一条消息时崩溃,而客户机却试图将其消息扔进空白处


感谢您提前给出答案,我真的需要解决这个问题。

您有一些小问题和一些大问题:

小型:

  • 您不会影响
    提示中的
    ai_协议
    ,但当
    提示
    不为
    NULL时,
    getaddrinfo()
    需要它
  • 您使用
    connect()
    的返回作为文件描述符,但它是一个错误代码号。必须在客户机中通过
    socket()
    或在服务器中通过
    accept()
    使用文件描述符返回
  • 在服务器中使用
    send()
    时使用了错误的文件描述符。您不应该在处理
    SOCK\u流中连接的文件描述符上发送数据
  • getaddrinfo()
    返回一个列表,您应该对它进行迭代,但您假设总是有一个结果,但它们可以是零或多个
  • 提示
    初始化后,您可以使用
    memset()
    调用未定义的行为,因为
    sizeof(struct addrinfo)>sizeof(struct addrinfo*)
    所以当您在
    ai
    上写零时(全局…全局无处不在)
大:

  • 你无缘无故地使用global
  • 您可以逐行声明多个变量
  • 你无缘无故地使用global
  • 您没有验证所有系统调用错误
  • 你无缘无故地使用global


好的,谢谢你们。我非常渴望解决这个问题。感谢所有的回答,尤其是@Stargateur和@user3629249

好的,有两件事我需要弄清楚,感谢你们,我现在明白了

  • 我需要使用正确的文件描述符,这似乎很明显,但我总是假设使用connect/accept中的connfd或套接字。然而,正如user3629249所说,客户端的connect方法只能告诉我们连接是否建立,但它不是一个描述符。因此,客户端需要使用套接字中的filedescriptor,在我的示例中是sockfd
  • 在服务器端,客户端的描述符由accept给出,因此我需要在我的示例中使用connfd

  • 因为我的uni,我已经必须使用一些严格的标志了,但是使用更严格的标志真的很有用。我一直对Java非常严格,但忘了在C语言中应用这种思想,因为C语言更重要
  • 所以我在下面发布了我对这个问题的解决方案,再次感谢大家!你让我开心!为了简单起见,头文件没有改变,但是在代码中还剩下一些东西。如果您使用类似的方法,请检查所有错误,如recv和send方法,并请阅读Stargateur和user3629249的评论,这将帮助您理解我的代码失败的原因,现在可以工作了

    生成文件

    CC      = /usr/bin/gcc
    CFLAGS  = -std=c99 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -g -c
    SERVER = server
    CLIENT = client
    
    all: $(SERVER).c $(CLIENT).c clean compile compile2
    
    compile: $(SERVER).c $(CLIENT).c 
      gcc $(CFLAGS) $(SERVER).c
      gcc $(CFLAGS) $(CLIENT).c
    
    compile2: $(SERVER).o $(CLIENT).o
      gcc $(SERVER).o -o $(SERVER)
      gcc $(CLIENT).o -o $(CLIENT)
    
    clean: $(SERVER) $(SERVER).o $(CLIENT) $(CLIENT).o
      rm $(SERVER) $(SERVER).o
      rm $(CLIENT) $(CLIENT).o
    
    客户

    #include "common.h"
    
    static char *port = DEFAULT_PORT;
    static char *host = DEFAULT_HOST;
    
    int main() {
      int s;
      struct addrinfo hints, *rp;
      memset(&ai, 0, sizeof(hints));
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE;
    
      s = getaddrinfo(host, port, &hints, &ai);
      if(s != 0) error("Couldn't get address info...\n");
    
      for (rp=ai; rp != NULL; rp=rp->ai_next) {
        sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if(sockfd == -1) continue;
        if((connfd = connect(sockfd, rp->ai_addr, rp->ai_addrlen)) != -1) break;
        close(sockfd);
      }
    
      if(rp == NULL) error("Couldn't connect...\n");
    
      uint8_t msg = 0x00;
      for(int i = 0; i < 10; ++i) {
        msg=(uint8_t)((int)msg+1);
        (void) fprintf(stdout, "Sending message %#X\n", msg);
        send(sockfd, &msg, 1, MSG_CONFIRM);
        recv(sockfd, &msg, 1, MSG_CONFIRM);
        (void) fprintf(stdout, "Recieved from Server %#X\n", msg);
      }
      free_ressources();
    }
    
    来自/客户

    ./client
    Sending message 0X1
    Recieved from Server 0X2
    Sending message 0X3
    Recieved from Server 0X4
    Sending message 0X5
    Recieved from Server 0X6
    Sending message 0X7
    Recieved from Server 0X8
    Sending message 0X9
    Recieved from Server 0XA
    Sending message 0XB
    Recieved from Server 0XC
    Sending message 0XD
    Recieved from Server 0XE
    Sending message 0XF
    Recieved from Server 0X10
    Sending message 0X11
    Recieved from Server 0X12
    Sending message 0X13
    Recieved from Server 0X14
    Freeing all ressources...
    

    “但我到处都看到我应该使用袜子。”什么?“无处不在”在哪里?accept()返回的套接字是绑定到客户端的套接字,因此您应该在发送/接收调用中使用它。@Stargateur Sry编辑了它,现在它包含了头too@MartinJames谢谢你的回复,是的,我被这个名字感动了。您是对的,不要将代码放在头文件中。不要在头文件中放置变量。编译时,请始终启用警告,然后修复这些警告。(对于
    gcc
    ,至少使用:
    -Wall-Wextra-Wconversion-pedantic-std=gnu11
    )所有这些都是大错误。事实上,你称之为“小”的那些比你称之为“大”的几个要大,它们实际上只是时尚宣言。@EJP取决于你的观点,对我来说,这些大问题是这些小问题的原因;)显然这只是个玩笑。谢谢你的回答,我现在将尝试使用你的信息,希望能解决这个问题。由于服务器的连接部分是给定的,我只需要验证错误,所以我认为这应该是正确的,但我现在将测试它
    // server and client
    struct addrinfo hints = {
      .ai_family = AF_INET,
      .ai_socktype = SOCK_STREAM,
      .ai_flags = AI_PASSIVE,
      .ai_protocol = IPPROTO_TCP,
    };
    // server
    if (send(connfd, &msg_s, 1, MSG_CONFIRM) == -1) {
      // error
    }
    // client
    if (recv(sockfd, &msg_r, 1, MSG_CONFIRM) == -1) {
      // error
    }
    
    CC      = /usr/bin/gcc
    CFLAGS  = -std=c99 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -g -c
    SERVER = server
    CLIENT = client
    
    all: $(SERVER).c $(CLIENT).c clean compile compile2
    
    compile: $(SERVER).c $(CLIENT).c 
      gcc $(CFLAGS) $(SERVER).c
      gcc $(CFLAGS) $(CLIENT).c
    
    compile2: $(SERVER).o $(CLIENT).o
      gcc $(SERVER).o -o $(SERVER)
      gcc $(CLIENT).o -o $(CLIENT)
    
    clean: $(SERVER) $(SERVER).o $(CLIENT) $(CLIENT).o
      rm $(SERVER) $(SERVER).o
      rm $(CLIENT) $(CLIENT).o
    
    #include "common.h"
    
    static char *port = DEFAULT_PORT;
    static char *host = DEFAULT_HOST;
    
    int main() {
      int s;
      struct addrinfo hints, *rp;
      memset(&ai, 0, sizeof(hints));
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE;
    
      s = getaddrinfo(host, port, &hints, &ai);
      if(s != 0) error("Couldn't get address info...\n");
    
      for (rp=ai; rp != NULL; rp=rp->ai_next) {
        sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if(sockfd == -1) continue;
        if((connfd = connect(sockfd, rp->ai_addr, rp->ai_addrlen)) != -1) break;
        close(sockfd);
      }
    
      if(rp == NULL) error("Couldn't connect...\n");
    
      uint8_t msg = 0x00;
      for(int i = 0; i < 10; ++i) {
        msg=(uint8_t)((int)msg+1);
        (void) fprintf(stdout, "Sending message %#X\n", msg);
        send(sockfd, &msg, 1, MSG_CONFIRM);
        recv(sockfd, &msg, 1, MSG_CONFIRM);
        (void) fprintf(stdout, "Recieved from Server %#X\n", msg);
      }
      free_ressources();
    }
    
    #include "common.h"
    
    static char *port = DEFAULT_PORT;
    
    uint16_t read_from_client();
    
    int main() {
      struct addrinfo hints;
      memset(&ai, 0, sizeof(hints));
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE;
      hints.ai_protocol = 0;
    
      int res = getaddrinfo(NULL, port, &hints, &ai);
      if(res != 0) error("Failed to get addr info: %s\n", gai_strerror(res));
    
      sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
      if(sockfd == -1) error("Couldn't create a socket\n");
    
      int val = 1;
      res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
      if(res == -1) error("Socket options couldn't be set\n");
    
      res = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
      if(res == -1) error("Socket binding failed\n");
    
      res = listen(sockfd, 1);
      if(res == -1) error("Listener setup failed\n");
    
      connfd = accept(sockfd, NULL, NULL);
      if(connfd == -1) error("Server Accept failed\n");
    
      uint8_t msg = 0x00;
      for(int i = 0; i < 10; ++i) {
        recv(connfd, &msg, 1, MSG_CONFIRM);   
        (void) fprintf(stdout, "Recieved from Client %#X\n", msg);
        msg = (uint8_t) ((int)msg + 1);
        (void) fprintf(stdout, "Sending %#X\n", msg);
        send(connfd, &msg, 1, MSG_CONFIRM);
      }
      free_ressources();
    }
    
    ./server 
    Recieved from Client 0X1
    Sending 0X2
    Recieved from Client 0X3
    Sending 0X4
    Recieved from Client 0X5
    Sending 0X6
    Recieved from Client 0X7
    Sending 0X8
    Recieved from Client 0X9
    Sending 0XA
    Recieved from Client 0XB
    Sending 0XC
    Recieved from Client 0XD
    Sending 0XE
    Recieved from Client 0XF
    Sending 0X10
    Recieved from Client 0X11
    Sending 0X12
    Recieved from Client 0X13
    Sending 0X14
    Freeing all ressources...
    
    ./client
    Sending message 0X1
    Recieved from Server 0X2
    Sending message 0X3
    Recieved from Server 0X4
    Sending message 0X5
    Recieved from Server 0X6
    Sending message 0X7
    Recieved from Server 0X8
    Sending message 0X9
    Recieved from Server 0XA
    Sending message 0XB
    Recieved from Server 0XC
    Sending message 0XD
    Recieved from Server 0XE
    Sending message 0XF
    Recieved from Server 0X10
    Sending message 0X11
    Recieved from Server 0X12
    Sending message 0X13
    Recieved from Server 0X14
    Freeing all ressources...