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 |
|
Не зарегистрирован
|
Огромное спасибо всем кто откликнулся. Буду копать далее. Еще раз спасибо.
|
|
|