C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Сокеты
Andrey
Отправлено: 07.07.2005, 16:16


Не зарегистрирован







Помогите разобраться с Сокетами.
Обьявляю
CODE

#include <winsock2.h>

SOCKET ServerSocket;

void Server()
{
   ::ServerSocket=socket(AF_INET, SOCK_STREAM, 0);
  if(::ServerSocket!=INVALID_SOCKET)
     {

Вот сюда не попадаю??
     }
   else
     MessageBox(NULL,"Achtung!!","Внимание",MB_OK);
   
}
вызов идет в виде
CODE

       try
       {
                Application->Initialize();
                Application->CreateForm(__classid(TForm1), &Form1);
                Server();
                Application->Run();
      }

Что я делаю не так и куда можно впихнуть ту часть, которая в приладе должна быть независимым сервером, ну кроме отдельного потока.

Отредактировано Георгий — 07/07/2005, 20:45
Konstantine
Отправлено: 08.07.2005, 08:13


Мастер участка

Группа: Модератор
Сообщений: 545



Andrey, ты и десятой части н сделал того, что нужно для запуска сервера... если хочешь — могу порыться по конспектам с универа...
а чем тебя TServerSocket и TClientSocket не устраивает?
Dima
Отправлено: 08.07.2005, 12:38


Дежурный стрелочник

Группа: Участник
Сообщений: 61



простой пример установки соединения
CODE

  int socket;
  struct sockaddr_in peer; // структура описывающая сервер
  WSADATA wsadata;
 
  int port = 2000;
  AnsiString Address = "127.0.0.1";

  WSAStartup(MAKEWORD(2,2), &wsadata);

  peer.sin_family = AF_INET;
  peer.sin_port = htons(port);

  // проверим, возможно Address содержит просто ip
  if( ( peer.sin_addr.s_addr = inet_addr(static_cast<const char*>(Address.data())) ) == (INADDR_NONE)) {
     // нет, не ip, тогда возможно это dns адрес
     struct hostent* h;
     h =gethostbyname( Address.c_str() );
     if( h == NULL) {
        return;  // перед этим надо вывести сообщение об ошибке
     }
     memcpy( &peer.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
  }

  //получить дескриптор сокета
  socket = ::socket(AF_INET, SOCK_STREAM, 0);

  if(socket == INVALID_SOCKET)
  {
     throw Exception("ошибка вызова socket ");
  }
  // установить соединение
  if( connect(socket, (struct sockaddr*)&peer, sizeof(peer)) != 0)
  {
     throw PException("ошибка вызова connect ");
  }
  вот теперь соединение установлено и можно передовать данные


Отредактировано Dima — 08/07/2005, 12:40
Andrey
Отправлено: 08.07.2005, 13:00


Не зарегистрирован







Да. Пожалуйста Константин. Буду ОЧЕНЬ признателен.
Я смотрел на
http://tangentsoft.net/wskfaq/examples/bas...ded-server.html
Но вот в том и проблема, что не хочет создавать даже сокет, черт с ним — с сервером.А сам сервер там создается бесконечным циклом в Майне, с отделением клиентов в отдельные треды.


2Dima:
Спасибо за описание, н отакой вопрос.
Обьявляем
struct sockaddr_in TestSocket;

Но почему выпадает
TestSocket.sin_addr.S_un.S_addr = INADDR_ANY;
то есть есть лишний член после sin_addr????
Dima
Отправлено: 11.07.2005, 07:13


Дежурный стрелочник

Группа: Участник
Сообщений: 61



sin_addr — это структура типа in_addr в которой обявлено обединение S_un в котором есть 3 поля для доступа к 4 байта по байтам , по словам и сразу к четырем байтам, там также обявлены псевдонимы , поэтому :
TestSocket.sin_addr.S_un.S_addr = INADDR_ANY; тоже самое что и
TestSocket.sin_addr.s_addr = INADDR_ANY;
что значит принимать соединения с любого сетевого интерфейса.
простой сервер:

CODE

  struct sockaddr_in local; // структура описывающая сервер
  struct sockaddr_in peer; // структура описывающая клиента
  int s; // дескриптор сокета открытого на прослушивание

  local.sin_family = AF_INET;
  local.sin_port = htons(port);
  local.sin_addr.s_addr = htonl(INADDR_ANY);

  s = socket(AF_INET, SOCK_STREAM, 0);
  if(s == INVALID_SOCKET)
  {
     throw Exception("ошибка вызова socket");
  }
  //привязываем адрес интерфейса и номер порта к прослушивающему сокету
  //определяет порт и сетевой интерфейс для прослушивания
  //для прослушивания конкретного интерфейса нужно указать его IP адрес
  rc = bind(s, (struct sockaddr*)&local, sizeof(local));
  if(rc == SOCKET_ERROR)
  {
     throw Exception("ошибка вызова bind");
  }
  //переводим сокет в режим прослушивания
  rc = listen(s, 10);
  if(rc == SOCKET_ERROR)
  {
     throw Exception("ошибка вызова listen");
  }
  //получить соединение из входной очереди
  int peerlen;

  //ждем пока клиент не попросит соединения
  int s1;
/*
после вызова функции accept управление к нам не вернется пока кто нибудь не подключится, поэтому можно использовать select с небольшим таймаутом в цикле и например отлавливать сигнал на зовершение программы
*/
  s1 = accept(s, (struct sockaddr*)&peer, &peerlen);
  server(s1, &peer); //функция обрабатывает соединение с клиентом


написать универсальный класс довольно трудно потому, что логика размыкания соединения , да и логика обработки ошибок во многом зависят от логики самого приложения
Andrey
Отправлено: 11.07.2005, 08:15


Не зарегистрирован







2Dima
Спасибо большое за пример кода.
Вопросик такой встает, если можно. Куда в Билдеровском приложении можно запихать данный код, чтобы он был сервером? То есть. Есть система мониторинга. Она работает постоянно но вот возникла потребность написать сетевую часть этого приложения, дабы можно было удаленно просматривать данные. Вот куда можно записать код, чтобы приложение слушало сеть постоянно?? Подскажите пожалуйста, куда копать.

Konstantine
Отправлено: 11.07.2005, 08:31


Мастер участка

Группа: Модератор
Сообщений: 545



QUOTE (Dima @ 11/07/2005, 07:13)
написать универсальный класс довольно трудно потому, что логика размыкания соединения , да и логика обработки ошибок во многом зависят от логики самого приложения

а зачем изобретать велосипед???
это УЖЕ есть в СТАНДАРТНОЙ поставке Билдера...
классы довольно удобны в использовании, тем более, что приложение Билдеровское....
ты представил пример БЛОКИРУЮЩЕГО сокета, который просто-напросто "вешает" поток до принятия соединения... а неблокирующий — он ещё сложнее... и ЗАЧЕМ???

Andrey, это нужно положить в отдельный поток и контролировать... но мой тебе совет прежний — TServerSocket и TClientSocket... на форуме про них много сказано
Dima
Отправлено: 11.07.2005, 09:20


Дежурный стрелочник

Группа: Участник
Сообщений: 61



Конечно, если задача не стоит делать что-то серьёзное, да и нет особого желания разбираться как это все работает, то конечно проще использовать стандартные компоненты, по поводу сложности реализовать все это самостоятельно — то это не правда. к тому коду что показан осталось только добавить две функции приёма и передачи данных по 20 строчек вот и все.
Andrey
Отправлено: 12.07.2005, 08:05


Не зарегистрирован







Огромное спасибо всем кто откликнулся. Буду копать далее. Еще раз спасибо.

Вернуться в Вопросы программирования в C++Builder