Как написать клиенту дважды?

#c #sockets

#c #сокеты

Вопрос:

Я пытаюсь отправить клиенту биты, которые он должен прочитать, затем он должен их прочитать. Но по какой-то причине он не читает сообщение, он читает только фрагменты, msgLength .Я получаю сообщение от сервера [server]The message was sent succefully. , и клиент может читать только то msgLength , msg что пусто.
клиент:

 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>

extern int errno;

int port;

int main(int argc, char *argv[])
{
  int sd;                   
  struct sockaddr_in server; 
  char msg[200];            
  int fd;
  char msgLength[200];

  
  if (argc != 3)
  {
    printf("Sintax: %s <adress_server> <port>n", argv[0]);
    return -1;
  }

  
  port = atoi(argv[2]);

 
  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("Error on socket().n");
    return errno;
  }


 
  server.sin_family = AF_INET;

  server.sin_addr.s_addr = inet_addr(argv[1]);

  server.sin_port = htons(port);


  if (connect(sd, (struct sockaddr *)amp;server, sizeof(struct sockaddr)) == -1)
  {
    perror("[client]Erorr on connect().n");
    return errno;
  }
     
  if (recv(sd, msgLength, 2,0) < 0)
  {
    perror("[client]Erorr on recv() from the server.n");
    return errno;
  }
  bzero(msg,100);
  if (recv(sd, msg, 22,0)<0){
    perror("[client]Erorr on the second recv() from the server.n");
    return errno;
  }
printf("msgLength: %sn",msgLength);
 
  printf("[client]The message recived is: %sn", msg);

  close(sd);
}

 

сервер:

 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>

#define PORT 2024


extern int errno;

int main()
{
  struct sockaddr_in server; r
  struct sockaddr_in from;
  char msg[100];           
  char msgrasp[100] = " "; 
  int sd;                  
  pid_t pid;

  
  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("[server]Erorr on the socket().n");
    return errno;
  }

  
  bzero(amp;server, sizeof(server));
  bzero(amp;from, sizeof(from));


  server.sin_family = AF_INET;

  server.sin_addr.s_addr = htonl(INADDR_ANY);

  server.sin_port = htons(PORT);

  int optval = 1;
  setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, amp;optval, sizeof(optval));
  setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, amp;optval, sizeof(optval));

    */
      if (bind(sd, (struct sockaddr *)amp;server, sizeof(struct sockaddr)) == -1)
  {
    perror("[server]Erorr on the bind().n");
    return errno;
  }

  if (listen(sd, 5) == -1)
  {
    perror("[server]Erorr on listen().n");
    return errno;
  }

 
  while (1)
  {
    int client;
    int length = sizeof(from);

    printf("[server]We wait on the port %d...n", PORT);
    fflush(stdout);

    
    client = accept(sd, (struct sockaddr *)amp;from, amp;length);

   
    if (client < 0)
    {
      perror("[server]Erorr on accept().n");
      continue;
    }

    switch (pid = fork())
    {
    case -1:
      perror("fork");
      exit(1);
      break;
    case 0:
      close(sd);
      
      bzero(msg, 100);
      printf("[server]Sending the text...n");
      fflush(stdout);

      int fd1 = open("ToSend.txt", O_RDONLY);
      char msgLength[100];
      read(fd1, msgrasp, 100);
      sprintf(msgLength,"%ld",strlen(msgrasp) 1);
      printf("msgLength: %dn",atoi(msgLength));

      
      if ((send(client,msgLength,sizeof(msgLength),0) amp;amp; send(client, msgrasp, atoi(msgLength),0)) <= 0)
      {
        perror("[server]Erorr on send() to the client.n");
        continue; 
      }
      else
        printf("[server]The message was sent succefully.n");

     
      exit(2);

    default:
      wait(NULL);
      close(client);
      break;
    }

  }
} 
 

Комментарии:

1. Вызовы send() и recv() действительно должны более тщательно проверять возвращаемые значения, особенно recv() для получения фактического количества полученных байтов.

2. Примите решение: является ли заявление об использовании сообщением об ошибке или оно информационное? Если это сообщение об ошибке, оно должно быть записано в stderr, и программа должна возвращать ненулевое значение. Если он информационный, его следует записать в стандартный вывод, и программа должна завершиться с нулевым значением. Запись сообщения в стандартный вывод и возврат -1 — это шизофрения. IMO, заявление об использовании не должно быть написано вместо правильного сообщения об ошибке, а недавнее распространение инструментов, которые выдают заявления об использовании вместо краткого сообщения об ошибке, является пародией.

3. @SteveFriedl Я проверил. Если сервер записывает n бит, recv от клиента возвращает n, но msg пусто

4. Вы не должны использовать strlen() для подсчета полученных байтов; вместо этого посмотрите на возвращаемое значение из recv() . И почему код делает это? printf("msgLength: %dn",atoi(msgLength)); после форматирования количества в строку?

5. Я сделал int recvB=recv(sd, msg, atoi(msgLength),0) , и я получил байты. И я делаю это printf("msgLength: %dn",atoi(msgLength)); только для печати, чтобы узнать, отправляет ли сервер правильную информацию

Ответ №1:

Я решил это. Проблема заключалась в том, что сервер отправлял sizeof(msgLength) witch 100, а клиент читал только 2. Если я заменю sizeof(msgLength) на strlen(msgLength) 1 него, он будет работать просто отлично. Спасибо всем за ваше время.