Программирование сокетов в Linux на C++.By Rob Tougher
Сокет - это механизм обмена данными между процессами .
Процессы могут находиться и на одной машине , и на разных .
После установки коннекта обмен данными может происходить в обоих направлениях.
Данная версия реализована с помощью т.н. raw socket . Приложение традиционно
состоит из клиента и сервера , которые реализованы с помощью классов
ClientSocket и ServerSocket.
2. Взаимодействие клиент-сервер
Следующая таблица показывает последовательность такого взаимодействия.
Server |
Client |
1. Установка слушающего сокета и ожидание запроса от клиента. |
|
|
2. Создание клиентского сокета и попытка законнектиться на сервер. |
3. Вылавливание клиентского коннекта. |
|
4. Отправка-получение данных |
4. Отправка-получение данных. |
5. Закрытие коннекта. |
5. Закрытие коннекта. |
Реализация простого сервера и клиента
Сервер - инициализация слушающего сокета :
#include "ServerSocket.h"
#include "SocketException.h"
#include <string>
int main ( int argc, int argv[] )
{
try
{
// Create the server socket
ServerSocket server ( 30000 );
// rest of code -
// accept connection, handle request, etc...
}
catch ( SocketException& e )
{
std::cout << "Exception :" << e.description() << "\nExiting.\n";
}
return 0;
}
Конструктор для ServerSocket инициализирует слушающий сокет .
Реализация класса ServerSocket :
// Implementation of the ServerSocket class
#include "ServerSocket.h"
#include "SocketException.h"
ServerSocket::ServerSocket ( int port )
{
if ( ! Socket::create() )
{
throw SocketException ( "Could not create server socket." );
}
if ( ! Socket::bind ( port ) )
{
throw SocketException ( "Could not bind to port." );
}
if ( ! Socket::listen() )
{
throw SocketException ( "Could not listen to socket." );
}
}
ServerSocket::~ServerSocket(){}
const ServerSocket& ServerSocket::operator << ( const std::string& s ) const
{
if ( ! Socket::send ( s ) )
{
throw SocketException ( "Could not write to socket." );
}
return *this;
}
const ServerSocket& ServerSocket::operator >> ( std::string& s ) const
{
if ( ! Socket::recv ( s ) )
{
throw SocketException ( "Could not read from socket." );
}
return *this;
}
void ServerSocket::accept ( ServerSocket& sock )
{
if ( ! Socket::accept ( sock ) )
{
throw SocketException ( "Could not accept socket." );
}
}
Обратите внимание на блок try/catch block.
Классы ServerSocket и ClientSocket
используют традиционную С++ обработку исключений .
Обработка исключений описана в SocketException.h:
// SocketException class
#ifndef SocketException_class
#define SocketException_class
#include < string >
class SocketException
{
public:
SocketException ( std::string s ) : m_s ( s ) {};
~SocketException (){};
std::string description() { return m_s; }
private:
std::string m_s;
};
#endif
Метод description() этого класса описывает саму ошибку .
Теперь клиент :
#include "ClientSocket.h"
#include "SocketException.h"
#include <iostream>
#include <string>
int main ( int argc, int argv[] )
{
try
{
// Create the client socket
ClientSocket client_socket ( "localhost", 30000 );
// rest of code -
// send request, retrieve reply, etc...
}
catch ( SocketException& e )
{
std::cout << "Exception :" << e.description() << "\n";
}
return 0;
}
При создании инстанса класса ClientSocket клиентский сокет
коннектится к хосту/порту .
Далее сервер слушает клиента и фиксирует попытки коннекта .
Чуть доработанная версия сервера :
#include "ServerSocket.h"
#include "SocketException.h"
#include <string>
int main ( int argc, int argv[] )
{
try
{
// Create the socket
ServerSocket server ( 30000 );
while ( true )
{
ServerSocket new_sock;
server.accept ( new_sock );
// rest of code -
// read request, send reply, etc...
}
}
catch ( SocketException& e )
{
std::cout << "Exception :" << e.description() << "\nExiting.\n";
}
return 0;
}
Отлавливание клиентских коннектов выполняется с помощью метода accept ,
который имеет параметр new_sock .
После того как мы поймали клиента , ему нужно дать знать об этом .
Одной из фич С++ является способность перегружать операторы ,
или создавать собственный вариант оператора .
В классах ClientSocket и ServerSocket
перегружаются стандартные операторы ввода-вывода << и >> :
#include "ServerSocket.h"
#include "SocketException.h"
#include <string>
int main ( int argc, int argv[] )
{
try
{
// Create the socket
ServerSocket server ( 30000 );
while ( true )
{
ServerSocket new_sock;
server.accept ( new_sock );
try
{
while ( true )
{
std::string data;
new_sock >> data;
new_sock << data;
}
}
catch ( SocketException& ) {}
}
}
catch ( SocketException& e )
{
std::cout << "Exception :" << e.description() << "\nExiting.\n";
}
return 0;
}
new_sock включает в себя всю информацию о сокете и используется
для обмена данных с клиентом.
Строка "new_sock >> data;" читает данные из сокета
и помещает их в строку 'data'."
Следующая строка посылает 'data' назад клиенту .
Это пример эхо-сервера . При этом клиент распечатывает ответ сервера :
#include "ClientSocket.h"
#include "SocketException.h"
#include <iostream>
#include <string>
int main ( int argc, int argv[] )
{
try
{
ClientSocket client_socket ( "localhost", 30000 );
std::string reply;
try
{
client_socket << "Test message.";
client_socket >> reply;
}
catch ( SocketException& ) {}
std::cout << "response from the server:\n\"" << reply << "\"\n";;
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\n";
}
return 0;
}
В данный проект входят следующие файлы :
- Miscellaneous:
- Makefile - the Makefile for this project
- Socket.h,
Socket.cpp - the
Socket class, which implements the raw socket API calls.
- SocketException.h - the SocketException class
- Server:
- simple_server_main.cpp - main file
- ServerSocket.h,
ServerSocket.cpp
- the ServerSocket class
- Client:
- simple_client_main.cpp - main file
- ClientSocket.h,
ClientSocket.cpp
- the ClientSocket class
Их можно целиком взять в архиве тут (10 кб) .
После компиляции будут созданы 2 бинарника .
Запускаем сервер :
prompt$ ./simple_server
running....
Теперь запускаем клиента :
prompt$ ./simple_client
We received this response from the server:
"Test message."
prompt$
Клиент посылает данные серверу , читает ответ и печатает его .
|
Мишаня | я не очень силен в С++, скачав архив при компиляции возникают ошибки,
версия компилятора
gcc version 3.2.3 (ALT Linux, build 3.2.3-alt3)
2006-02-09 14:32:42 | JO | жуть просто
одно s=buf чего стоит
я уже не говорю про close в деструкторе
ЛЮДИ!!! даже не пытайтесь юзать этот бред - кроме проблем ничего не получите 2008-05-09 23:30:12 | Дмитрий | так я не понял допустим я хочу одиночную игру сделать онлайн то мне надо что то качать программы для мулбтиплеера все эти
атрибуты 2012-12-03 22:08:22 | Влад | Я хочу ту же Готику 3 воплотить в онлайн, ну то есть в мультиплеер как это сделать
покажи видео урок поучительный расскажи подробно если захочешь? 2012-12-03 22:12:19 | |
|
|