Написание TCP-сервера на WinSock на Borland C++ Builder 6 с возможностью видеть сообщения от клиентов и отправлять им

Гобелен - кликните для возврата на главную

Не прошло и месяца а Фурмановская ЦРБ в очередной раз попала в историю. На этот раз сотрудница клеветала на пациентов, а именно огласку получил случай когда сотрудница назвала пациента алкашём.

Так почему бы не начать использовать обход блокировки YouTube при том что техническая возможность используя расширение nikolaevevge для браузера Mozilla Firefox уже появилась, а объем полезной(и не очень) информации на видеохостинге YouTube, по мнению некоторых диванных экспертов, меньше не стал.

Ровно 3 года назад произошло событие, которое подарило жителям планеты Змеля новый чистый праздник 6 апреля - в этот замечательный день земля забрала гнить негодяя и СПАМера Владимира Вольфовича Жириновского.

Как бы не обстояли дела в области культуры и IT-технологий, Самосвал писал статьи на связанные темы и планирует ещё написать.

На очередном конкурсе танцев, школьница отлично выступила.

Что использовать вместо Юбуст

Вот та самая информация: программа для продвижения канала YouTube, эта информация выложена уже несколько лет, при этом просмотров не много, а метод который описан в данном видео действительно помогает продвигать видео в YouTube.

Начал разбираться с информацией которая находится в HTTPS клиентском запросе рукопожатия.

Обратите внимание! Объект изображённый на гобилене может отличаться от общепринятого вида описанного объекта. Тут дело в том что художник видит именно так!

104 549 руб.

Описание товара

На форме находится Button1 - кнопка старта сервера, Button2 - кнопка остановки сервера, ListBox1 - список клиентов(которые в настоящий момент подключены к серверу), Memo1 - список сообщений(от клиентов и им), Edit1 - поле ввода сообщения для клиента, Button3 - кнопка отправки сообщения из Edit1 клиенту который выбран в ListBox1, Edit2 - поле для задания порта(применяется в момент старта сервера). TCP-сервер реализауется через WinSock.

Файл Unit1.h

C++
    
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <winsock2.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:
    TButton *Button1;
    TButton *Button2;
    TListBox *ListBox1;
    TMemo *Memo1;
    TEdit *Edit1;
    TButton *Button3;
    TLabel *Label1;
    TEdit *Edit2;
    TLabel *Label2;
    
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
    void __fastcall Button3Click(TObject *Sender);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall ListBox1Click(TObject *Sender);
      
private:
    SOCKET ListenSocket;
    HANDLE ServerThread;
    bool ServerRunning;
    TList* ClientSockets;
    CRITICAL_SECTION csClientList;
    int ServerPort;
    AnsiString LogMessage;
    TStringList* ClientListItems;
    bool EnableSendButton;
    
    void AddToLog(AnsiString msg);
    void UpdateClientList();
    void RemoveClient(SOCKET clientSocket);
    static DWORD WINAPI ServerThreadProc(LPVOID lpParam);
    static DWORD WINAPI ClientThreadProc(LPVOID lpParam);
    void SendToClient(SOCKET clientSocket, AnsiString message);
    bool StartServer(int port);
    void StopServer();
    void __fastcall AddLogToMemo();
    void __fastcall UpdateClientListBox();
    void __fastcall EnableSendButtonProc();
      
public:
    __fastcall TForm1(TComponent* Owner);
    __fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

  

Файл Unit1.cpp

C++
    
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <stdio.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    InitializeCriticalSection(&csClientList);
    ClientSockets = new TList;
    ListenSocket = INVALID_SOCKET;
    ServerThread = NULL;
    ServerRunning = false;
    ServerPort = 12345;
    ClientListItems = new TStringList;
}
//---------------------------------------------------------------------------
      
__fastcall TForm1::~TForm1()
{
    StopServer();
    DeleteCriticalSection(&csClientList);
    delete ClientSockets;
    delete ClientListItems;
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        ShowMessage("Ошибка инициализации Winsock");
        Button1->Enabled = false;
        return;
    }
      
    Edit2->Text = "12345";
    Button1->Enabled = true;
    Button2->Enabled = false;
    Button3->Enabled = false;
    AddToLog("Сервер готов к запуску. Введите порт и нажмите 'Старт сервера'");
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::AddLogToMemo()
{
    Memo1->Lines->Add(LogMessage);
}
//---------------------------------------------------------------------------
      
void TForm1::AddToLog(AnsiString msg)
{
    LogMessage = FormatDateTime("hh:nn:ss", Now()) + " - " + msg;
    TThread::Synchronize(NULL, AddLogToMemo);
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::UpdateClientListBox()
{
    ListBox1->Items->BeginUpdate();
    ListBox1->Items->Assign(ClientListItems);
    ListBox1->Items->EndUpdate();
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::EnableSendButtonProc()
{
    Button3->Enabled = EnableSendButton;
}
//---------------------------------------------------------------------------
      
void TForm1::UpdateClientList()
{
    EnterCriticalSection(&csClientList);
    try
    {
        ClientListItems->Clear();
        EnableSendButton = false;
        
        for (int i = 0; i < ClientSockets->Count; i++)
        {
            SOCKET s = (SOCKET)ClientSockets->Items[i];
            sockaddr_in clientAddr;
            int addrLen = sizeof(clientAddr);
            if (getpeername(s, (sockaddr*)&clientAddr, &addrLen) == 0)
            {
                AnsiString clientInfo = inet_ntoa(clientAddr.sin_addr) + AnsiString(":") + IntToStr(ntohs(clientAddr.sin_port));
                ClientListItems->Add(clientInfo);
            }
        }
        
        EnableSendButton = (ClientSockets->Count > 0 && ListBox1->ItemIndex >= 0);
    }
    __finally
    {
        LeaveCriticalSection(&csClientList);
    }
    
    TThread::Synchronize(NULL, UpdateClientListBox);
    TThread::Synchronize(NULL, EnableSendButtonProc);
}
//---------------------------------------------------------------------------
      
bool TForm1::StartServer(int port)
{
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET)
    {
        AddToLog("Ошибка создания сокета: " + IntToStr(WSAGetLastError()));
        return false;
    }
      
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(port);
      
    if (bind(ListenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
    {
        AddToLog("Ошибка bind: " + IntToStr(WSAGetLastError()));
        closesocket(ListenSocket);
        ListenSocket = INVALID_SOCKET;
        return false;
    }
      
    if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        AddToLog("Ошибка listen: " + IntToStr(WSAGetLastError()));
        closesocket(ListenSocket);
        ListenSocket = INVALID_SOCKET;
        return false;
    }
      
    ServerRunning = true;
    ServerThread = CreateThread(NULL, 0, ServerThreadProc, this, 0, NULL);
    return true;
}
//---------------------------------------------------------------------------
      
void TForm1::StopServer()
{
    if (!ServerRunning) return;
      
    ServerRunning = false;
    
    if (ListenSocket != INVALID_SOCKET)
    {
        closesocket(ListenSocket);
        ListenSocket = INVALID_SOCKET;
    }
      
    if (ServerThread)
    {
        WaitForSingleObject(ServerThread, INFINITE);
        CloseHandle(ServerThread);
        ServerThread = NULL;
    }
      
    EnterCriticalSection(&csClientList);
    for (int i = 0; i < ClientSockets->Count; i++)
    {
        SOCKET s = (SOCKET)ClientSockets->Items[i];
        closesocket(s);
    }
    ClientSockets->Clear();
    LeaveCriticalSection(&csClientList);
}
//---------------------------------------------------------------------------
      
DWORD WINAPI TForm1::ServerThreadProc(LPVOID lpParam)
{
    TForm1* form = (TForm1*)lpParam;
    SOCKET listenSocket = form->ListenSocket;
      
    while (form->ServerRunning)
    {
        sockaddr_in clientAddr;
        int addrLen = sizeof(clientAddr);
        SOCKET clientSocket = accept(listenSocket, (sockaddr*)&clientAddr, &addrLen);
        
        if (clientSocket == INVALID_SOCKET)
        {
            if (form->ServerRunning)
                form->AddToLog("Ошибка accept: " + IntToStr(WSAGetLastError()));
            continue;
        }
      
        EnterCriticalSection(&form->csClientList);
        form->ClientSockets->Add((void*)clientSocket);
        LeaveCriticalSection(&form->csClientList);
      
        AnsiString clientInfo = inet_ntoa(clientAddr.sin_addr) + AnsiString(":") + IntToStr(ntohs(clientAddr.sin_port));
        form->AddToLog("Клиент подключен: " + clientInfo);
        form->UpdateClientList();
      
        form->SendToClient(clientSocket, "Добро пожаловать на сервер! Ваш ID: " + clientInfo);
      
        HANDLE hThread = CreateThread(NULL, 0, ClientThreadProc, (LPVOID)new std::pair<TForm1*, SOCKET>(form, clientSocket), 0, NULL);
        CloseHandle(hThread);
    }
      
    return 0;
}
//---------------------------------------------------------------------------
      
DWORD WINAPI TForm1::ClientThreadProc(LPVOID lpParam)
{
    auto params = (std::pair<TForm1*, SOCKET>*)lpParam;
    TForm1* form = params->first;
    SOCKET clientSocket = params->second;
    delete params;
      
    char buffer[1024];
    int bytesReceived;
      
    while (form->ServerRunning)
    {
        bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
        
        if (bytesReceived <= 0)
        {
            if (bytesReceived == SOCKET_ERROR)
                form->AddToLog("Ошибка чтения от клиента: " + IntToStr(WSAGetLastError()));
            break;
        }
      
        buffer[bytesReceived] = '\0';
        AnsiString message(buffer);
      
        sockaddr_in clientAddr;
        int addrLen = sizeof(clientAddr);
        getpeername(clientSocket, (sockaddr*)&clientAddr, &addrLen);
        AnsiString clientInfo = inet_ntoa(clientAddr.sin_addr) + AnsiString(":") + IntToStr(ntohs(clientAddr.sin_port));
      
        form->AddToLog("[" + clientInfo + "]: " + message);
      
        if (message.LowerCase() == "exit")
        {
            form->SendToClient(clientSocket, "До свидания!");
            break;
        }
      
        form->SendToClient(clientSocket, "ECHO: " + message);
    }
      
    closesocket(clientSocket);
    form->RemoveClient(clientSocket);
      
    form->AddToLog("Клиент отключен");
    form->UpdateClientList();
      
    return 0;
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int port = StrToIntDef(Edit2->Text, 0);
    if (port <= 0 || port > 65535)
    {
        AddToLog("Неверный номер порта. Допустимый диапазон: 1-65535");
        return;
    }
      
    ServerPort = port;
    
    if (StartServer(ServerPort))
    {
        Button1->Enabled = false;
        Button2->Enabled = true;
        Edit2->Enabled = false;
        AddToLog("Сервер запущен на порту " + IntToStr(ServerPort));
    }
    else
    {
        AddToLog("Не удалось запустить сервер на порту " + IntToStr(ServerPort));
    }
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    StopServer();
    
    Button1->Enabled = true;
    Button2->Enabled = false;
    Button3->Enabled = false;
    Edit2->Enabled = true;
    ListBox1->Clear();
    AddToLog("Сервер остановлен");
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::Button3Click(TObject *Sender)
{
    if (ListBox1->ItemIndex < 0) return;
    
    AnsiString message = Edit1->Text;
    if (message.IsEmpty()) return;
      
    EnterCriticalSection(&csClientList);
    try
    {
        if (ListBox1->ItemIndex >= 0 && ListBox1->ItemIndex < ClientSockets->Count)
        {
            SOCKET clientSocket = (SOCKET)ClientSockets->Items[ListBox1->ItemIndex];
            SendToClient(clientSocket, message);
            
            sockaddr_in clientAddr;
            int addrLen = sizeof(clientAddr);
            getpeername(clientSocket, (sockaddr*)&clientAddr, &addrLen);
            AnsiString clientInfo = inet_ntoa(clientAddr.sin_addr) + AnsiString(":") + IntToStr(ntohs(clientAddr.sin_port));
            
            AddToLog("Сервер -> [" + clientInfo + "]: " + message);
            Edit1->Clear();
        }
    }
    __finally
    {
        LeaveCriticalSection(&csClientList);
    }
}
//---------------------------------------------------------------------------
      
void TForm1::SendToClient(SOCKET clientSocket, AnsiString message)
{
    if (send(clientSocket, message.c_str(), message.Length(), 0) == SOCKET_ERROR)
    {
        AddToLog("Ошибка отправки сообщения: " + IntToStr(WSAGetLastError()));
        RemoveClient(clientSocket);
        UpdateClientList();
    }
}
//---------------------------------------------------------------------------
      
void TForm1::RemoveClient(SOCKET clientSocket)
{
    EnterCriticalSection(&csClientList);
    try
    {
        int index = ClientSockets->IndexOf((void*)clientSocket);
        if (index >= 0)
        {
            ClientSockets->Delete(index);
        }
    }
    __finally
    {
        LeaveCriticalSection(&csClientList);
    }
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    StopServer();
    WSACleanup();
}
//---------------------------------------------------------------------------
      
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
    Button3->Enabled = (ListBox1->ItemIndex >= 0);
}
//---------------------------------------------------------------------------

  

Другие товары

Вы так же можете прочитать следующие статьи: