Сервер UDP-клиент c ++: sendto, recvfrom - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь завершить простой эхо-сервер. Цель состоит в том, чтобы повторить сообщение клиенту. Сервер и клиент компилируются. Сервер привязан к localhost и порту 8080. У клиента есть адрес, порт и сообщение. Когда клиент проходит через программу в раздел sendto, он останавливается и ждет там. Моя цель - отправить его на сервер, а сервер отправить обратно.

Проблема: клиент отправляет сообщение, а сервер получает его правильно, но сервер не может вернуть сообщение. Пожалуйста помоги!

КОД СТОРОНЫ СЕРВЕРА:

#include <iostream>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080

using namespace std;

int main() {
  int serSockDes, len, readStatus;
  struct sockaddr_in serAddr, cliAddr;
  char buff[1024] = {0};
  char msg[] = "Hello to you too!!!\n";

  //creating a new server socket
  if((serSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket creation error...\n");
    exit(-1);
  }

  //binding the port to ip and port
  serAddr.sin_family = AF_INET;
  serAddr.sin_port = htons(PORT);
  serAddr.sin_addr.s_addr = INADDR_ANY;

  if((bind(serSockDes, (struct sockaddr*)&serAddr, sizeof(serAddr))) < 0) {
    perror("binding error...\n");
    exit(-1);
  }

  readStatus = recvfrom(serSockDes, buff, 1024, 0, (struct sockaddr*)&cliAddr, (socklen_t*)&len);
  buff[readStatus] = '\0';
  cout<<buff;

  cout<<len;

  sendto(serSockDes, msg, strlen(msg), 0, (struct sockaddr*)&cliAddr, len);

  return 0;
}

КОД СТОРОНЫ КЛИЕНТА:

#include <iostream>
#include <fstream>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080

using namespace std;

int main(int argc, char** argv) {
  int cliSockDes, readStatus, len;
  struct sockaddr_in serAddr;
  char msg[] = "Hello!!!\n";
  char buff[1024] = {0};

  //create a socket
  if((cliSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket creation error...\n");
    exit(-1);
  }

  //server socket address
  serAddr.sin_family = AF_INET;
  serAddr.sin_port = htons(PORT);
  serAddr.sin_addr.s_addr = INADDR_ANY;

  sendto(cliSockDes, msg, strlen(msg), 0, (struct sockaddr*)&serAddr, sizeof(serAddr));

  readStatus = recvfrom(cliSockDes, buff, 1024, 0, (struct sockaddr*)&serAddr, (socklen_t*)&len);
  buff[readStatus] = '\0';
  cout<<buff;

  return 0;
}

1 Ответ

0 голосов
/ 30 октября 2018

Клиент пытается отправить сообщение на INADDR_ANY, что неверно. Вместо этого необходимо отправить на определенный IP-адрес. Сервер может прослушивать все свои локальные IP-адреса, используя INADDR_ANY, это нормально, но IP-адрес, на который отправляет клиент, должен быть тем, который прослушивает сервер (или, если клиент и сервер находятся в разных сегментах сети) клиент должен отправить IP-адрес, который достигает маршрутизатора сервера, который затем должен переслать сообщение на IP-адрес, который прослушивает сервер).

Кроме того, ваши звонки на recvfrom() и sendto() на обоих концах не имеют адекватной обработки ошибок. В частности, параметр addrlen recvfrom() указывает максимальный размер буфера sockaddr при вводе и при выводе возвращает фактический размер адреса однорангового узла, сохраненного в sockaddr. Но вы не инициализируете переменную len, которую передаете, как addrlen, поэтому recvfrom() может завершиться с ошибкой, которую вы не обрабатываете.

Попробуйте вместо этого что-нибудь более похожее:

Сервер:

#include <iostream>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;

#define PORT 8080

int main() {
  int serSockDes, readStatus;
  struct sockaddr_in serAddr, cliAddr;
  socklen_t cliAddrLen;
  char buff[1024] = {0};
  char msg[] = "Hello to you too!!!\n";

  //creating a new server socket
  if ((serSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket creation error...\n");
    exit(-1);
  }

  //binding the port to ip and port
  serAddr.sin_family = AF_INET;
  serAddr.sin_port = htons(PORT);
  serAddr.sin_addr.s_addr = INADDR_ANY;

  if ((bind(serSockDes, (struct sockaddr*)&serAddr, sizeof(serAddr))) < 0) {
    perror("binding error...\n");
    close(serSockDes);
    exit(-1);
  }

  cliAddrLen = sizeof(cliAddr);
  readStatus = recvfrom(serSockDes, buff, 1024, 0, (struct sockaddr*)&cliAddr, &cliAddrLen);
  if (readStatus < 0) { 
    perror("reading error...\n");
    close(serSockDes);
    exit(-1);
  }

  cout.write(buff, readStatus);
  cout << endl;

  if (sendto(serSockDes, msg, strlen(msg), 0, (struct sockaddr*)&cliAddr, cliAddrLen)) < 0) { 
    perror("sending error...\n");
    close(serSockDes);
    exit(-1);
  }

  close(serSockDes);
  return 0;
}

Клиент:

#include <iostream>
#include <fstream>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;

#define PORT 8080

int main(int argc, char** argv) {
  int cliSockDes, readStatus;
  struct sockaddr_in serAddr;
  socklen_t serAddrLen;
  char msg[] = "Hello!!!\n";
  char buff[1024] = {0};

  //create a socket
  if ((cliSockDes = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket creation error...\n");
    exit(-1);
  }

  //server socket address
  serAddr.sin_family = AF_INET;
  serAddr.sin_port = htons(PORT);
  serAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

  if (sendto(cliSockDes, msg, strlen(msg), 0, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) {
    perror("sending error...\n");
    close(cliSockDes);
    exit(-1);
  }

  serAddrLen = sizeof(serAddr);
  readStatus = recvfrom(cliSockDes, buff, 1024, 0, (struct sockaddr*)&serAddr, &serAddrLen);
  if (readStatus < 0) {
    perror("reading error...\n");
    close(cliSockDes);
    exit(-1);
  }

  cout.write(buff, readStatus);
  cout << endl;

  close(cliSockDes);
  return 0;
}
...