Пример сервера для программы обмена сообщениями между клиентами и сервером
#include<stdio.h>
#include<winsock2.h>// Wincosk2.h долженбыть
// подключенраньшеwindows.h!
#include<windows.h>
#defineMY_PORT 666
// Порт, который слушает сервер
// макрос для печати количества активных
// пользователей
#definePRINTNUSERSif (nclients)\
printf("%d user on-line\n",nclients);\
elseprintf("No User on line\n");
// прототипфункции, обслуживающий
// подключившихсяпользователей
DWORDWINAPISexToClient(LPVOIDclient_socket);
// глобальная переменная – количество
// активных пользователей
intnclients = 0;
int main(intargc, char* argv[])
{
charbuff[1024]; // Буфер для различных нужд
printf("TCP SERVER DEMO\n");
// Шаг 1 - Инициализация Библиотеки Сокетов
// Т.к. возвращенная функцией информация
// не используется ей передается указатель на
// рабочий буфер, преобразуемый
// к указателю на структуру WSADATA.
// Такой прием позволяет сэкономить одну
// переменную, однако, буфер должен быть не менее
// полкилобайта размером (структура WSADATA
// занимает 400 байт)
if (WSAStartup(0x0202, (WSADATA *)&buff[0]))
{
// Ошибка!
printf("Error WSAStartup %d\n",
WSAGetLastError());
return -1;
}
// Шаг 2 - созданиесокета
SOCKETmysocket;
// AF_INET - сокет Интернета
// SOCK_STREAM - потоковый сокет (с
// установкой соединения)
// 0 - по умолчанию выбирается TCP протокол
|
|
if ((mysocket = socket(AF_INET, SOCK_STREAM, 0))<0)
{
// Ошибка!
printf("Error socket %d\n", WSAGetLastError());
WSACleanup();
// Деиницилизациябиблиотеки Winsock
return -1;
}
// Шаг 3 связывание сокета с локальным адресом
sockaddr_inlocal_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(MY_PORT);
// не забываем о сетевом порядке!!!
local_addr.sin_addr.s_addr = 0;
// сервер принимает подключения
// на все IP-адреса
// вызываем bind длясвязывания
if (bind(mysocket, (sockaddr *)&local_addr,
sizeof(local_addr)))
{
// Ошибка
printf("Error bind %d\n", WSAGetLastError());
closesocket(mysocket); // закрываемсокет!
WSACleanup();
return -1;
}
// Шаг 4 ожидание подключений
// размер очереди – 0x100
if (listen(mysocket, 0x100))
{
// Ошибка
printf("Error listen %d\n", WSAGetLastError());
closesocket(mysocket);
WSACleanup();
return -1;
}
|
|
printf("Waiting for client\n");
// Шаг 5 извлекаем сообщение из очереди
SOCKETclient_socket; // сокет для клиента
sockaddr_inclient_addr; // адресклиента
// (заполняется системой)
// функции accept необходимо передать размер
// структуры
intclient_addr_size = sizeof(client_addr);
// цикл извлечения запросов на подключение из
// очереди
while ((client_socket = accept(mysocket, (sockaddr *)
&client_addr, &client_addr_size)))
{
nclients++; // увеличиваем счетчик
// подключившихся клиентов
// пытаемся получить имя хоста
HOSTENT *hst;
hst = gethostbyaddr((char *)
&client_addr.sin_addr.s_addr, 4, AF_INET);
// выводсведенийоклиенте
printf("+%s [%s] new connect!\n",
|
|
(hst) ? hst->h_name : "",
inet_ntoa(client_addr.sin_addr));
PRINTNUSERS
// Вызов нового потока для обслуживания клиента
// Да, для этого рекомендуется использовать
// _beginthreadex но, поскольку никаких вызов
// функций стандартной Си библиотеки поток не
// делает, можно обойтись и CreateThread
DWORDthID;
CreateThread(NULL, NULL, SexToClient,
&client_socket, NULL, &thID);
}
return 0;
}
// Эта функция создается в отдельном потоке и
// обсуживает очередного подключившегося клиента
// независимо от остальных
DWORDWINAPISexToClient(LPVOIDclient_socket)
{
SOCKETmy_sock;
my_sock = ((SOCKET *)client_socket)[0];
char buff[20 * 1024];
#definesHELLO"Hello, Sailor\r\n"
// отправляем клиенту приветствие
send(my_sock, sHELLO, sizeof(sHELLO), 0);
// цикл эхо-сервера: прием строки от клиента и
// возвращение ее клиенту
intbytes_recv;
while ((bytes_recv =
|
|
recv(my_sock, &buff[0], sizeof(buff), 0))
&&bytes_recv != SOCKET_ERROR)
{
printf("%s", buff);
send(my_sock, &buff[0], bytes_recv, 0);
}
// если мы здесь, то произошел выход из цикла по
// причине возращения функцией recv ошибки –
// соединение клиентом разорвано
nclients--; // уменьшаем счетчик активных клиентов
printf("-disconnect\n"); PRINTNUSERS
// закрываемсокет
closesocket(my_sock);
return 0;
}
Примерклиента:
// Пример простого TCP клиента
#include<stdio.h>
#include<string.h>
#include<winsock2.h>
#include<windows.h>
#definePORT 666
#defineSERVERADDR"127.0.0.1"
int main(intargc, char* argv[])
{
char buff[1024];
printf("TCP DEMO CLIENT\n");
// Шаг 1 - инициализациябиблиотеки Winsock
if (WSAStartup(0x202, (WSADATA *)&buff[0]))
{
printf("WSAStart error %d\n", WSAGetLastError());
return -1;
}
// Шаг 2 - созданиесокета
SOCKETmy_sock;
my_sock = socket(AF_INET, SOCK_STREAM, 0);
if (my_sock< 0)
{
printf("Socket() error %d\n", WSAGetLastError());
return -1;
}
// Шаг 3 - установка соединения
// заполнение структуры sockaddr_in
// указание адреса и порта сервера
sockaddr_indest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(PORT);
HOSTENT *hst;
// преобразование IP адреса из символьного в
// сетевойформат
if (inet_addr(SERVERADDR) != INADDR_NONE)
dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);
else
// попытка получить IP адрес по доменному
// имени сервера
if (hst = gethostbyname(SERVERADDR))
// hst->h_addr_list содержит не массив адресов,
// а массив указателей на адреса
((unsignedlong *)&dest_addr.sin_addr)[0] =
((unsignedlong **)hst->h_addr_list)[0][0];
else
{
printf("Invalid address %s\n", SERVERADDR);
closesocket(my_sock);
WSACleanup();
return -1;
}
// адрес сервера получен – пытаемся установить
// соединение
if (connect(my_sock, (sockaddr *)&dest_addr,
sizeof(dest_addr)))
{
printf("Connect error %d\n", WSAGetLastError());
return -1;
}
printf("Соединение с %s успешно установлено\n\
Type quit for quit\n\n", SERVERADDR);
// Шаг 4 - чтение и передача сообщений
intnsize;
while ((nsize = recv(my_sock, &buff[0],
sizeof(buff) - 1, 0))
!=SOCKET_ERROR)
{
// ставим завершающий ноль в конце строки
buff[nsize] = 0;
// выводимнаэкран
printf("S=>C:%s", buff);
// читаем пользовательский ввод с клавиатуры
printf("S<=C:"); fgets(&buff[0], sizeof(buff) - 1,
stdin);
// проверкана "quit"
if (!strcmp(&buff[0], "quit\n"))
{
// Корректный выход
printf("Exit...");
closesocket(my_sock);
WSACleanup();
return 0;
}
// передаем строку клиента серверу
send(my_sock, &buff[0], nsize, 0);
}
printf("Recv error %d\n", WSAGetLastError());
closesocket(my_sock);
WSACleanup();
return -1;
}
Дата добавления: 2018-05-13; просмотров: 202; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!