Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Клиент-сервер на сокетах

439
02 июля 2005 года
Rexulnik
217 / / 09.02.2005
Как реализовать клиент-сервер на сокетах?
Т.е. программа запущенная на локальной машине
ждёт комманд, и когда получает их от сервера, то выполняет соответствующие действия... например, запускает какие-нибудь функции...
2.9K
20 июля 2005 года
pushkin
43 / / 13.09.2004
Цитата:
Originally posted by Rexulnik
Как реализовать клиент-сервер на сокетах?
Т.е. программа запущенная на локальной машине
ждёт комманд, и когда получает их от сервера, то выполняет соответствующие действия... например, запускает какие-нибудь функции...



Это сделать достаточно просто. Если использовать Microsoft Visual C++ 6/7/8, то можно создать консольное приложение-сервер с примерно таким кодом:

#include <iostream>
#include <winsock2.h> // Включаем использование сокетов
#pragma comment(lib, "WSock32.lib") // Используем эту библиотеку

using namespace std;

void main()
{
WSADATA wsa_data; // Информация о сокетах
SOCKET s; // Серверный сокет

s = NULL;

// 1. Инициализируем сокеты (требуем версию 1.1 как минимум)
if (WSAStartup(0x101,&wsa_data) != 0) return;

// 2. Открываем серверный сокет
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) return;

// 3. Привязываем сокет к адресу
sockaddr_in addr; // Для хранения адреса
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_port = htons(777); // Наш порт, который будем открывать для коннектов
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) != 0) return;

// 4. Устанавливаем сокет в режим прослушивания
if (listen(s, 1) == SOCKET_ERROR) return;

// 5. Бесконечный цикл получения соединений
while (true)
{
// Принимаем соединения от клиентов
int from_len;
SOCKET client_socket; // Сокет клиента
sockaddr_in client_addr; // Адрес клиента

from_len = sizeof(client_addr);
client_socket = accept(s, (LPSOCKADDR)&client_addr, &from_len);

// Проверяем ошибочность соединения
if (client_socket == INVALID_SOCKET)
continue; // Если что опять переходим в режим ожидания соединения

cout << "Client connected [" << inet_ntoa(client_addr.sin_addr) << "]..." << endl;

// Обмениваемся данными с клиентом.
// Тут должны быть вызовы функций send и recv. Функция recv, если что,
// ждет пока клиент что-нибудь пошлет, send отсылает данные и сразу
// возвращает управление программе

// Отсылаем "приветствие" подключившемуся клиенту
char *greeting = "Fuck off!!!";
send(client_socket, greeting, (int)strlen(greeting),0);

// Получаем ответ клиента
char buf[1024];
int len = recv(client_socket, buf, 1024, 0);
if (len != SOCKET_ERROR)
{
buf[len] = 0; // Не забываем ставить терминирующий ноль (если мы строку принимаем)
cout << buf << endl;
}

// Закрываем сокет
closesocket(client_socket);

// Переходим к следующему клиенту
cout << "...disconnected" << endl;
}

// 6. Закрываем серверный сокет
closesocket(s);

// 7. Завершаем работу с сокетами
WSACleanup();
}


Вот пример простого клиента для такого сервера:

#include <iostream>
#include <winsock2.h> // Включаем использование сокетов
#pragma comment(lib, "WSock32.lib") // Используем эту библиотеку

using namespace std;

void main()
{
WSADATA wsa_data; // Информация о сокетах
SOCKET s; // Серверный сокет

s = NULL;

// 1. Инициализируем сокеты (требуем версию 1.1 как минимум)
if (WSAStartup(0x101,&wsa_data) != 0) return;

// 2. Открываем серверный сокет
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) return;

// 3. Привязываем сокет к адресу
sockaddr_in addr; // Для хранения адреса
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(777); // Наш порт, который будем открывать для коннектов
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) != 0) return;

// 4. Соединяемся
if (connect(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
return;

// 5. Обмениваемся данными
// (получаем приветствие)
char buf[1024];
int len = recv(s, buf, 1024, 0);
if (len == SOCKET_ERROR) return;

buf[len] = 0;

// Отсылаем ответ серверу
char *reply = "Fuck you too, buddy!";
send(s, reply, (int)strlen(reply), 0);

// 6. Закрываем сокет
closesocket(s);

// 7. Завершаем работу с сокетами
WSACleanup();
}

31K
07 ноября 2009 года
DeniSS1
5 / / 14.08.2007
Почему-то некорректно работает клиент, а возможно, и сервер (а возможно, и руки..) - bind(s, (LPSOCKADDR)&addr, sizeof(addr)) почему-то возвращает 0. К тому же, при попытке пропинговать запущенный сервер (ping 127.0.0.1:777) командная строка пишет "узел не найден".
Help me!
31K
07 ноября 2009 года
DeniSS1
5 / / 14.08.2007
Всё, проблема решена! :-) Вместо сравнения с 0 нужно сравнивать с SOCKET_ERROR.
31K
07 ноября 2009 года
DeniSS1
5 / / 14.08.2007
Ещё такой вопрос - почему-то если указать вместо адреса в локальной сети свой интернет-ip, то соединение через 777 порт не устанавливается :-(
А если коннектиться через 23, то устанавливается, но приходят крякозябры. :-(
288
09 ноября 2009 года
nikitozz
1.2K / / 09.03.2007
Цитата: DeniSS1
Ещё такой вопрос - почему-то если указать вместо адреса в локальной сети свой интернет-ip, то соединение через 777 порт не устанавливается :-(



Настройки файрволла?

53K
10 ноября 2009 года
plenlytep
10 / / 29.10.2009
Здравствуйте может кто сталкивался с проблеммой каким образом создать приложение клиент-сервер для работы с базой данных в dbf формате. Запросы должны идти от клинета в серверную часть программы устновленной на другом компьютере и возвращать данные по запросу клиенту. База именно dbfная. Открывать базу по сети тоже не катит, надо не всю базу, а лишь некоторые записи из нее. Как это организовать на Делфях?
288
10 ноября 2009 года
nikitozz
1.2K / / 09.03.2007
Цитата: plenlytep
каким образом создать приложение клиент-сервер для работы с базой данных в dbf формате.



Руками очевидно. Написать сервер и написать клиент. :) Задавайте конкретные вопросы, чтобы получить кокретные ответы.

Цитата: plenlytep

Как это организовать на Делфях?



И не забываем читать название раздела, в котором создаем топик.

54K
10 ноября 2009 года
CharlesUE
2 / / 06.11.2009
Добрый день, возникла у меня проблемка.
Значит есть система следующая: клиент заходит на определенный сайт, вводит некоторые данные и отправляет их на сервер системы. Следом, уже с сервера системы идет запрос на другой сервер в биллинг поставщика услуг. Причем устроено это так:

Всего на одну операцию идет два запроса:
1 Создание транзакции в системе биллинга оператора
2 Подтверждение этой транзакции без этого не будет операции

Запросы даются по HTTPS просто GET запросом, в ответ дается XML с данными транзакциями.

Так вот все вроде идеально работает, НО бывает такое:
1 Серверная часть системы отсылает запрос на создание транзакции, получает ответ - и все ок.
2 Следом она отправляет запрос на подтверждение транзакции.......... и тут
3 что-то случается с каналом связи между поставщиком услуг и моей серверной частью. Соединение отрывает по таймАуту.

Соответственно система думает что просто никакой ответ не пришел, а следовательно платеж не проведен. Хотя по сути то биллингу оператора похрен получил я данные назад или нет. И в результате в их биллинге операция прошла а в моем нет.
Потом когда наши бухгалтеры делают сверку, то оказывается что некоторые данные потеряны. И их руками приходится вбивать. В день такая погрешность в среднем 1 - а это около 10 операций в месяц 300........ руками вбивать сложно. И парсер не могу написать чтобы автоматом вбивать погрешность так как поставщик услуг не присылает данные о потерянных платежах в текстовом виде, они делаю просто скриншот .

Как с этим бороться? :?
есть идея сразу писать данные о соединениях, которые были по тайм-ауту отброшены, но тоже не выйдет, так как XML ответ на подтверждение транзакции все равно потом не дают, а там основное что мне нужно. VPN соединение между серверами тоже поднимать никто не хочет..
____________________________
Не грозит здоровью кризис, если лечит doctorbusiness Реформа здравоохранения и таблетки
288
10 ноября 2009 года
nikitozz
1.2K / / 09.03.2007
Менять канал связи. :)
Хотя если обрыв происходит именно при поптыке подтвердить платеж у поставщика, то возможно дело не в связи а в косяке на стороне поставщика или вашего серверного приложения.
Вообще у вас как-то странно сервер работает. Если запрос на создание прошел успешно, а запрос на подтверждение нет, то система совсем не должна думать, что платеж не совершен. Как минимум платеж должен быть выставлен в состояние создан, но не потдвержден для дальнейшей обработки его ручками.
31K
10 ноября 2009 года
DeniSS1
5 / / 14.08.2007
nikitozz, в том то и дело, что файрвола у меня нет.
Всё, пошёл читать статью http://www.insidepro.com/kk/006/006r.shtml
31K
10 ноября 2009 года
DeniSS1
5 / / 14.08.2007
Путём проб и ошибок установлено, что соединение по интернет-ip устанавливается только на портах, которые у меня открыты постоянно (21, 23, 80). Выводится интересный текст, так что я, похоже, подключаюсь к telnet-у, ftp и т.д. (логично, в приниципе). Серевер при этом слушает эти же порты.
Ни на какие другие порты подключение не проходит. Может ли это быть из-за того, что я запускаю сервер и клиент на одном и том же компе?
288
11 ноября 2009 года
nikitozz
1.2K / / 09.03.2007
Давайте код.
14
12 ноября 2009 года
Phodopus
3.3K / / 19.06.2008
Еще и схему сети с интернетом было бы полезно. А то мне начинает казаться что там lan-модем.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог