Теоретическое введение.
Сокет (socket) - это конечная точка сетевых коммуникаций. Он является чем-то вроде "портала", через которое можно отправлять байты во внешний мир
С каждым сокет связываются три атрибута: домен, тип и протокол.
int socket(int domain, int type, int protocol);
Домен определяет пространство адресов, в котором располагается сокет, и множество протоколов, которые используются для передачи данных. Чаще других используются домены Unix и Internet, задаваемые константами AF_UNIX и AF_INET соответственно (префикс AF означает "address family" - "семейство адресов"). При задании AF_UNIX для передачи данных используется файловая система ввода/вывода Unix. В этом случае сокеты используются для межпроцессного взаимодействия на одном компьютере и не годятся для работы по сети. Константа AF_INET соответствует Internet-домену. Сокеты, размещённые в этом домене, могут использоваться для работы в любой IP-сети. Существуют и другие домены (AF_IPX для протоколов Novell, AF_INET6 для новой модификации протокола IP - IPv6 и т. д.).
Тип сокета определяет способ передачи данных по сети. Чаще других применяются:
SOCK_STREAM. Передача потока данных с предварительной установкой соединения. Обеспечивается надёжный канал передачи данных, при котором фрагменты отправленного блока не теряются, не переупорядочиваются и не дублируются. Совместное использование с параметром AF_INET связывает сокет с протоколом TCP.
SOCK_DGRAM. Передача данных в виде отдельных сообщений (датаграмм). Предварительная установка соединения не требуется. Обмен данными происходит быстрее, но является ненадёжным: сообщения могут теряться в пути, дублироваться и переупорядочиваться. Допускается передача сообщения нескольким получателям (multicasting) и широковещательная передача (broadcasting). Совместное использование с параметром AF_INET связывает сокет с протоколом UDP
|
SOCK_RAW. Этот тип присваивается низкоуровневым (т. н. "сырым") сокетам. Их отличие от обычных сокетов состоит в том, что с их помощью программа может взять на себя формирование некоторых заголовков, добавляемых к сообщению.
.). При передаче в функцию bind указатель на эту структуру приводится к указателю на sockaddr.
Рассмотрим для примера структуру sockaddr_in.
struct sockaddr_in {
short int sin_family; // Семейство адресов
unsigned short int sin_port; // Номер порта
struct in_addr sin_addr; // IP-адрес
unsigned char sin_zero[8]; // "Дополнение" до размера структуры sockaddr
};
На стороне клиента для установления соединения используется функция connect, которая имеет следующий прототип.
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Здесь sockfd - сокет, который будет использоваться для обмена данными с сервером, serv_addr содержит указатель на структуру с адресом сервера, а addrlen - длину этой структуры.
Функция send используется для отправки данных и имеет следующий прототип.
int send(int sockfd, const void *msg, int len, int flags);
Здесь sockfd - это, как всегда, дескриптор сокета, через который мы отправляем данные, msg - указатель на буфер с данными, len - длина буфера в байтах, а flags - набор битовых флагов, управляющих работой функции
Для чтения данных из сокета используется функция recv.
int recv(int sockfd, void *buf, int len, int flags);
В целом её использование аналогично send
Закончив обмен данными, закройте сокет с помощью функции close (под Windows closesocket).Это приведёт к разрыву соединения.
closesocket(tcp_socket);
|
close(tcp_socket);
Код программы (С++):
#include <iostream.h> //для cin и cout
#include <winsock2.h> //для сокетов
char bufRus[1024]; //буфер для функции Rus
char* Rus(const char* text) //функция для вывода кириллицы в консоль
{
CharToOem(text, bufRus); //функция для перевода кодировки
return bufRus;
}
int main()
{
WSADATA Data;
WSAStartup(MAKEWORD(2,2),&Data); //подготовка к работе библиотеки Winsock
char message[1024]; //массив символов для сообщения
char buf[1024] = ""; //массив символов для принятого сообщения
SOCKET sock; //объявление сокета
struct sockaddr_in addr;
cout<<Rus("Клиент работает по протоколу UDP\n");
sock = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_family = AF_INET; //используется пространство адресов Internet
addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
while(1)
{
cout<<Rus("\nВведите ваше сообщение или напишите \"daytime\" для получения текущего времени: \n");
gets (message); //ввод сообщения
if (strcmp(message, "daytime") == 0)addr.sin_port = htons(13);
else addr.sin_port = htons(7);
cout<<Rus("Получено: ");
sendto(sock, message, sizeof(message), 0, (struct sockaddr *)&addr, sizeof(addr));
recvfrom(sock, buf, 1024, 0, NULL, NULL);
cout<<Rus(buf)<<endl;
}
closesocket(sock); //закрытие сокета
WSACleanup(); //деинициализация библиотеки WINSOCK
system("pause"); //пауза
return 0;}