Odbieranie danych od serwera -sockety linux

0

Witam mam do was wielką prośbę o pomoc w rozwiązaniu problemu odbierania przez klienta napisanego w c++ wiadomości od serwera.
Problem mój polega na tym, że serwer wysyła dane i tu niby wszystko jest ok do klienta (testuje wyniki poprzez funkcje napisane przez siebie
wyslij : int wyslij(int sock, string wiadomosc) oraz
odbierz: char * odbierz(int sock, char * buf)

Po moim tescie z serwera otrzymuje takie dane:

Czekam na polaczenie
52 Wyslalem do klienta bytow: 53 wiadomosc o tresci:" ===============Witaj administratorze===============
"
22 Wyslalem do klienta bytow: 23 wiadomosc o tresci:" 1. Dodaj uzytkownika
"
31 Wyslalem do klienta bytow: 32 wiadomosc o tresci:" 2. Zmien status uzytkownikowi
"
27 Wyslalem do klienta bytow: 28 wiadomosc o tresci:" 3. Zmien imie uzytkownika
"
31 Wyslalem do klienta bytow: 32 wiadomosc o tresci:" 4. Zmien nazwisko uzytkownika
"
28 Wyslalem do klienta bytow: 29 wiadomosc o tresci:" 5. Zmien haslo uzytkownika
"
24 Wyslalem do klienta bytow: 25 wiadomosc o tresci:" 6. Wypisz uzytkownikow
"
13 Wyslalem do klienta bytow: 14 wiadomosc o tresci:" 7. Wyjscie
"
52 Wyslalem do klienta bytow: 53 wiadomosc o tresci:" ===================================================
"
19 Wyslalem do klienta bytow: 20 wiadomosc o tresci:" Co mam zrobic ? :
"
1 Wyslalem do klienta bytow: 2 wiadomosc o tresci:" v"

I tu wydaje mi się że wszystko powinno być ok serwer wysyła po kolei menu do klienta.

Natomiast na kliencie otrzymuje dane w takie:

Odebralem od klienta bytow: 53 wiadomosc o tresci:"===============Witaj administratorze===============
"
Odebralem od klienta bytow: 144 wiadomosc o tresci:" 1. Dodaj uzytkownika
"
Odebralem od klienta bytow: 25 wiadomosc o tresci:" 6. Wypisz uzytkownikow
"


Nie rozumiem dlaczego 1 treść jest ok 53 znaki natomiast kolejne juz się nie zgadzają 2 wiersz powinien odebrać 32 znaki a odbiera 144.

Proszę pomóżcie w niedziele mam zaliczenie a nie mogę skończyc projektu bo nie wiem co się dzieje.

Poniżej już obcięty do minimum kod serwera i klienta.

SERWER

 
#define PORT 2323
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <string>
#include<iostream>

#define SERVER (127 << 24 | 0 << 16 | 0 << 8 | 1)
using namespace std; 
void wypisz_opcje_dostepne_do_wykonania_dla_administratora(int &sock) ;
int wyslij(int sock, string wiadomosc);

void error(char *msg)
{
  fprintf(stderr, "%s: %s\n", msg, strerror(errno));
  exit(1);
}


int open_listener_socket()
{
  int s = socket(PF_INET, SOCK_STREAM, 0);
  if (s == -1)
    error("Nie mozna otworzyc gniazda");
  return s;
}

void bind_to_port(int socket, int port)
{
  struct sockaddr_in name;
  name.sin_family = PF_INET;
  name.sin_port = (in_port_t)htons(PORT);
  name.sin_addr.s_addr = htonl(INADDR_ANY);
  int reuse = 1;
  if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(int)) == -1)
    error("Nie mozna ustawic opcji ponownego uzycia gniazda");
  int c = bind (socket, (struct sockaddr *) &name, sizeof(name));
  if (c == -1)
    error("Nie mozna utworzyc powiazania z gniazdem");
}


int listener_d;
void handle_shutdown(int sig)
{
  if (listener_d)
    close(listener_d);

  fprintf(stderr, "Na razie!\n");
  exit(0);
}


int main(int argc, char *argv[])
{
 
  listener_d = open_listener_socket();
  bind_to_port(listener_d, 30000);
  if (listen(listener_d, 10) == -1)
    error("Nie mozna odbierac polaczen");
  struct sockaddr_storage client_addr;
  unsigned int address_size = sizeof(client_addr);
  puts("Czekam na polaczenie");
  char buf[255];

  while (1) {
 
      int connect_d = accept(listener_d, (struct sockaddr *)&client_addr, &address_size);

    if (connect_d == -1)
      error("Nie mozna otworzyc pomocniczego gniazda");

    if (!fork()) {
      close(listener_d);
                
            wypisz_opcje_dostepne_do_wykonania_dla_administratora(connect_d);
      
      close(connect_d);
      exit(0);
    }
    close(connect_d);
  }


  return 0;
}


void wypisz_opcje_dostepne_do_wykonania_dla_administratora(int &sock) 
{

    string message[] = 
    {
        "===============Witaj administratorze===============\n",
        "\t1. Dodaj uzytkownika\n",
        "\t2. Zmien status uzytkownikowi\n",
        "\t3. Zmien imie uzytkownika\n",
        "\t4. Zmien nazwisko uzytkownika\n",
        "\t5. Zmien haslo uzytkownika\n",
        "\t6. Wypisz uzytkownikow\n",
        "\t7. Wyjscie \n",
        "===================================================\n",
        "Co mam zrobic ? :\n ",
        "v"
    };
   
    for (int i = 0; i < (sizeof (message) / sizeof (string)); i++) 
    {
        int ile = message[i].length();
        cout << ile << " ";
        
        wyslij(sock, message[i].c_str());
    }
   

}


int wyslij(int sock, string wiadomosc) {
    int ile = 0;
    ile = write(sock, wiadomosc.c_str(), wiadomosc.length() + 1);
    cout << "Wyslalem do klienta bytow: " << ile << " wiadomosc o tresci:\" " << wiadomosc << "\"\n";
    return ile;

}

char * odbierz(int sock, char * buf) {

    int ile = 0;
    ile = read(sock, buf, 256);
    cout << "Odebralem od klienta bytow: " << ile << " wiadomosc o tresci:\"" << buf << "\"" << endl;
    return buf;
}




KIIENT

 
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>

#define MAX_BUFFER 128

#define SERVER (127 << 24 | 0 << 16 | 0 << 8 | 1)

using namespace std;

char * odbierz(int sock, char * buf) 
{
    int ile = 0;
    ile = read(sock, buf, 256);
    cout << "Odebralem od klienta bytow: " << ile << " wiadomosc o tresci:\"" << buf << "\"" << endl;
    return buf;
}


int main (int argc, char *argv[] )
{
  int sock;
  int port=2323;

  struct sockaddr_in servaddr;
  sock = socket(PF_INET, SOCK_STREAM, 0);

  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(port);

  servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

 connect(sock, (struct sockaddr *)&servaddr,sizeof(servaddr)) ;

  char buf[256];
  
  while(1)
  {
      if(strcmp(odbierz(sock,buf),"v")==0) break;
  }
  

  return(0);
}


1
  1. Odpowiedź jest prosta - protokół TCP pozwala na sklejanie wielu małych wiadomości w jedną dużą. Dlatego wystarczą 3 read-y do odebrania wszystkiego.
  2. Twoje logi w kliencie są zbugowane bo pokazują tylko część buf-a do znaku końca linii. Zamiast jednego cout-a wypisuj całego buf-a np. for-em znak po znaku.
  3. Kod jest paskudny. Następnym razem oczyść go chociaż trochę. Jeśli umieścisz na forum ładny, czytelny kod szybciej dostaniesz odpowiedź.
0

Bardzo dziękuje za podpowiedź bardzo mi pomogłeś.

1 użytkowników online, w tym zalogowanych: 0, gości: 1