Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.12.2012, 16:55   #1
Freedo
Пользователь
 
Регистрация: 16.10.2012
Сообщений: 27
По умолчанию Обмен сообщеними по UDP

Здравствуйте, пишу чат по UDP. Хочу добиться вот чего, запускается сервер и два клиента. На первом клиенте пишется сообщение, и отправляется на сервер, оттуда оно передаётся на второй клиент.

Но получается вот что. Запускаю сервер и два клиента, на одном клиенте пишу сообщение, оно отправляется на сервер а затем обратно к тому же клиенту, до втрого ни чего не доходит, просто на сервер и обратно.

Помогите пожалуйста, как заставить его обмениваться сообщениями, широковещательно или с указанием адреса того кому нужно отправить без разницы.

Вот код сервера.

Код:
 // UDP сервер
  #pragma comment ( lib, "ws2_32.lib" )
  #include <stdio.h>
  #include <winsock2.h>

#include <iostream>

using namespace std;

  int main()
  {
	
	char buff[1024];	

    printf("UDP Server Started\n");

    // Инициализация WinSock
	WORD wVersionRequested = MAKEWORD (2,2);
	WSADATA wsaData;
    int err = WSAStartup(wVersionRequested, &wsaData);
	if (err !=0) 
    {
      printf("WSAStartup error: %d\n",WSAGetLastError());
    }
	else printf("WinSock intializing\n");

    // Открытие и закрытие сокета
    SOCKET my_sock = socket(AF_INET,SOCK_DGRAM,0);
    if (my_sock==INVALID_SOCKET)
    {
      printf("Socket error: %d\n",WSAGetLastError());
      WSACleanup();
    }

    // Связывание сокета 
    sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_addr.s_addr=htonl(INADDR_ANY);
    sin.sin_port=htons(5150);

    if (bind(my_sock,(sockaddr *) &sin, sizeof(sin))==SOCKET_ERROR)
    {
      printf("bind error: %d\n",WSAGetLastError());
      closesocket(my_sock);
    }

    
	// Обработка присланных пактов
	while(1)													
	{
		sockaddr_in client_addr;												
		int client_addr_size = sizeof(client_addr);					
		int bsize= recvfrom(my_sock,&buff[0],sizeof(buff)-1,0, (sockaddr *) &client_addr, &client_addr_size);
		if (bsize==SOCKET_ERROR)												
		printf("recvfrom() error: %d\n",WSAGetLastError());						


      // Определяем IP-адрес клиента и прочие атрибуты
	  HOSTENT *hostent;
      hostent = gethostbyaddr((char *)&client_addr.sin_addr,4,AF_INET);
      printf("accepted connection from %s, port %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
	  
	  // Добавление завершающего нуля
	  buff[bsize]=0;

		        // Вывод на экран 
      printf("C=>S:%s\n",&buff[0]);

      // посылка датаграммы клиенту
      sendto(my_sock,&buff[0],bsize,0,
        (sockaddr *)&client_addr, sizeof(client_addr));

  }
return 0;
  }

Вот код клиента.

Код:
// UDP-клиент
  #pragma comment ( lib, "ws2_32.lib" )
  #include <stdio.h>
  #include <string.h>
  #include <winsock2.h>
  #include <windows.h>
  #include <iostream>

using namespace std;
	


  int main()
  {
	char SERVERADDR[4];
    char buff[10*1014];

    printf("UDP Client Started\n");

	// Инициализация WinSock
	WORD wVersionRequested = MAKEWORD (2,2);
	WSADATA wsaData;
    int err = WSAStartup(wVersionRequested, &wsaData);
	if (err !=0) 
    {
      printf("WSAStartup error: %d\n",WSAGetLastError());
    }


    // Открытие и закрытие сокета
    SOCKET my_sock=socket(AF_INET, SOCK_DGRAM, 0);
    if (my_sock==INVALID_SOCKET)
    {
      printf("socket() error: %d\n",WSAGetLastError());
      WSACleanup();
    }

	printf("Enter Server IP: ");
	gets(SERVERADDR);

    // Шаг 3 - обмен сообщений с сервером
    HOSTENT *hostent;
    sockaddr_in dest_addr;

    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(5150);
	

    // определение IP-адреса узла
    if (inet_addr(SERVERADDR))
      dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
    else
      if (hostent=gethostbyname(SERVERADDR))
        dest_addr.sin_addr.s_addr=((unsigned long **)
              hostent->h_addr_list)[0][0];
    else
      {
        printf("Unknown host: %d\n",WSAGetLastError());
        closesocket(my_sock);
        WSACleanup();
        return -1;
      }

    while(1)
    {
      // чтение сообщения с клавиатуры
      printf("C=>S:");fgets(&buff[0],sizeof(buff)-1,stdin);
      if (!strcmp(&buff[0],"quit\n")) break;

      // Передача сообщений на сервер
      sendto(my_sock,&buff[0],strlen(&buff[0]),0, (sockaddr *) &dest_addr,sizeof(dest_addr));

      // Прием сообщения с сервера
      sockaddr_in server_addr;
      int server_addr_size=sizeof(server_addr);

      int n=recvfrom(my_sock,&buff[0],sizeof(buff)-1,0, (sockaddr *) &server_addr, &server_addr_size);

      if (n==SOCKET_ERROR)
      {
        printf("recvfrom() error:"\
          "%d\n",WSAGetLastError());
        closesocket(my_sock);
        WSACleanup();
        return -1;
      }

      buff[n]=0;

      // Вывод принятого с сервера сообщения на экран
      printf("S=>C:%s",&buff[0]);
    }

    // шаг последний - выход
    closesocket(my_sock);
    WSACleanup();

    return 0;
  }
Freedo вне форума Ответить с цитированием
Старый 26.12.2012, 21:56   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...достаточно использовать широковещательные запросы и понятие сервер-клиента станет относительным, все будут получать сообщения от всех.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 26.12.2012, 22:05   #3
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Вам надо хранить адреса всех активных клиентов и когда получите сообщение от одного посылать его всем кроме того, от кого получено. У вас будет куча проблем, начиная с того, кого хранить в списке активных контактов и кончая тем, что делать, если сообщение не дойдет до клиента и/или до сервера.
waleri вне форума Ответить с цитированием
Старый 26.12.2012, 22:17   #4
Freedo
Пользователь
 
Регистрация: 16.10.2012
Сообщений: 27
По умолчанию

Программа не будет использоваться как какое-то решение, всё что от неё требуется это включить её на разных компах и написать друг другу сообщения. То-есть она нужна на один раз.

Я пробовал добавить широковещательные запросы, но поскольку с C++ я знаком где-то неделю, и единственное что я делал до этого чата был "Hello World", поэтому естественно у меня ни чего не получилось. Я пробовал прописывать sin.sin_addr.s_addr=htonl(INADDR_BR OADCAST) и т.д, но кроме сообщения о переполнения буфера при компиляции ничего не получил.

Если это не очень трудно, не могли бы Вы показать, что и на что нужно заменить, что-бы она уже заработала?
Freedo вне форума Ответить с цитированием
Старый 26.12.2012, 23:36   #5
Freedo
Пользователь
 
Регистрация: 16.10.2012
Сообщений: 27
По умолчанию

Насколько я понял, если все адреса в моей локальной сети начинаются на "192.168.1.", то широковещательный запрос будет выглядеть вот так "192.168.1.255"?

Так вот у меня появилась идея, предложить пользователю на выбор либо указать IP компьютера которому нужно отправить сообщение, либо выбрать широковещательное послание. Поэтому я добавил следующий код:

Код:
char otvet[4];
	char broadcast[4];
	char IP[4];

	printf("Do yo connect broadcast or IP connection?");
	gets(otvet);

	if (otvet==broadcast)
	{
    #define SERVERADDR "192.168.1.255"
	}

	if (otvet==IP)
	{
    printf("Enter Server IP: ");
	gets(SERVERADDR);
	}
Но, чтобы я не писал соединение судя по всему осуществляется по "192.168.1.255". Как мне сделать чтобы выбор работал нормально?
Freedo вне форума Ответить с цитированием
Старый 30.12.2012, 00:10   #6
Freedo
Пользователь
 
Регистрация: 16.10.2012
Сообщений: 27
По умолчанию

Вобщем программа почти готова, подскажите пожалуйста, мне нужно, чтобы большие сообщения разбивались на отдельные меченные фрагменты. Как этого добиться? Подскажите хотя-бы источники на эту тему.
Freedo вне форума Ответить с цитированием
Старый 30.12.2012, 00:22   #7
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

Цитата:
чтобы большие сообщения разбивались на отдельные меченные фрагменты
определите для себя размер, далее делите и закидывайте в массив пакетов с определенной структурой и уже шлете его.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 30.12.2012, 00:38   #8
Freedo
Пользователь
 
Регистрация: 16.10.2012
Сообщений: 27
По умолчанию

Скажите в выше написанный код трудно будет встроить эту возможность. Правда я немного изменил код, теперь несколько клиентов посылают сообщения на сервер, а он их просто принимает и выводит на экран, но не суть.

С С++ я практически не знаком, только по этому заданию, поэтому без примеров мне пока трудно разобраться, может кто сможет помочь мне за отдельную плату, потому как я с этими делениями на фрагменты не разберусь ни как? Там большой объём работы, что-бы реализовать это?
Freedo вне форума Ответить с цитированием
Старый 09.01.2013, 00:26   #9
f3arnil
Пользователь
 
Регистрация: 15.12.2010
Сообщений: 15
По умолчанию

Цитата:
Сообщение от Freedo Посмотреть сообщение
Вобщем программа почти готова, подскажите пожалуйста, мне нужно, чтобы большие сообщения разбивались на отдельные меченные фрагменты. Как этого добиться? Подскажите хотя-бы источники на эту тему.
не поделитесь исходниками? тоже в этом направлении разбираюсь, было бы полезно посмотреть на конечный вариант
f3arnil вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
UDP обмен данными Dima DDM Работа с сетью в Delphi 0 21.11.2011 22:37
Обмен байтами через Udp Dima DDM Работа с сетью в Delphi 8 03.01.2011 04:19
Потоки UDP и.в.т. peplenko Помощь студентам 0 13.12.2010 23:12
прочитать UDP AmonRa Работа с сетью в Delphi 0 22.11.2010 06:32