C#クライアントを備えたシンプルで高速なC / C ++サーバー:TCPバージョン

みなさんこんにちは。 本のシートをゆっくりとソートし、サーバー側のプログラミングを行います。 そして、私の考えでは、サーバーをC ++で作成することまでやりました。 まあ、二度考えることなく(より正確には、まったく考えず、プラスをよく知らないで)、私はサーバーを書きに行きました。



そして、私はさまざまなエラーに出くわし始めましたが、それは以前は私には異質でしたが、構文は理解できませんでした。 そして最後に、最も簡単なサーバーであっても、どのように書くべきか、どのように書かないべきかを共有します。

さあ、行きます。



最も重要な要素であるSServerサーバークラスから始めましょう。



#pragma once #include "includes.h" class SServer { public: SServer(); ~SServer(); void startServer(); void closeServer(); void handle(); unsigned short port; private: SOCKET this_s; WSAData wData; };
      
      





ここでは難しいことではないと思います。 SOCKETをサーバーのソケットとして作成します。サーバーはリッスンします。

WSADataは、Windowsでソケットの使用をアクティブにするために必要です。



それが見出しでした。 CPPに進みましょう。



 #include "SServer.h" #include "includes.h" SServer::SServer(){ } SServer::~SServer(){ } void SServer::startServer(){ if (WSAStartup(MAKEWORD(2, 2), &wData) == 0) { printf("WSA Startup succes\n"); } SOCKADDR_IN addr; int addrl = sizeof(addr); addr.sin_addr.S_un.S_addr = INADDR_ANY; addr.sin_port = htons(port); addr.sin_family = AF_INET; this_s = socket(AF_INET, SOCK_STREAM, NULL); if (this_s == SOCKET_ERROR) { printf("Socket not created\n"); } if (bind(this_s, (struct sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR) { printf("Socket succed binded\n"); } if (listen(this_s, SOMAXCONN) != SOCKET_ERROR){ printf("Start listenin at port%u\n", ntohs(addr.sin_port)); } handle(); } void SServer::closeServer() { closesocket(this_s); WSACleanup(); cout << "Server was stoped. You can close app" << endl; } void SServer::handle() { while (true) { SOCKET acceptS; SOCKADDR_IN addr_c; int addrlen = sizeof(addr_c); if ((acceptS = accept(this_s, (struct sockaddr*)&addr_c, &addrlen)) != 0) { printf("send\n"); printf("sended Client connected from 0 %u.%u.%u.%u:%u\n", (unsigned char)addr_c.sin_addr.S_un.S_un_b.s_b1, (unsigned char)addr_c.sin_addr.S_un.S_un_b.s_b2, (unsigned char)addr_c.sin_addr.S_un.S_un_b.s_b3, (unsigned char)addr_c.sin_addr.S_un.S_un_b.s_b4, ntohs(addr_c.sin_port)); SClient* client = new SClient(acceptS, addr_c); } Sleep(50); } }
      
      





そして今、順番に。 まず、WSAStartup()を呼び出してWSAをアクティブにします。 MAKEWORDは、接続するライブラリのバージョンとWSADataオブジェクトへの参照を設定します。 通常、Unixがない場合にのみ、常に正常に動作します。 さらに。 SOCKADDR_IN構造は、サーバーのポートと可用性を事前に決定するのに役立ちます。 そして今、私は説明します:





次に、3つの関数呼び出して、SOCKET_ERRORでそれらの値をチェックする魔法があります。 ここでは多かれ少なかれ明確だと思います。 初期化、バインド、および強制的にリッスンします。



SOCK_STREAMは、それぞれTCPプロトコルSOCK_DGRAM-UDPの使用について説明します。

着信接続ハンドル()のハンドラーを呼び出し、無限ループでチェックを開始します。

着信接続用のソケット、アドレスを入力する構造、および構造の長さを作成します。

作成したソケットが、コンピューターからのそのようなアドレスに接続されていないことを確認します。 そして、すべてが順調であれば、メッセージを表示し、クライアントのアドレスから接続し、将来すべてを処理するクライアントを作成します。



クライアントコード。 見出しと実装を一緒に:



 #pragma once #include "includes.h" class SClient { public: SClient(SOCKET s, SOCKADDR_IN sock_in); ~SClient(); void handle(); private: SOCKET c_sock; SOCKADDR_IN c_addr; char buffer[1024]; }; SClient::SClient(SOCKET s, SOCKADDR_IN sock_in) { c_sock = s; c_addr = sock_in; printf("Client created\n"); handle(); } SClient::~SClient() { } void SClient::handle() { while (true) { int k = recv(c_sock, buffer, sizeof(buffer), NULL); if(k>0){ printf(buffer); } Sleep(30); } }
      
      





ここでも、ご覧のとおり、複雑なことは何もありません。 主なものは、コンストラクタですぐに実行するhandle()関数です。 recv()関数は、それぞれTCPで、recvfrom()はUDPプロトコルで使用するのが望ましいです。



そして最後に。 main.cppでは、次のようになります。



 #include "SServer.h" int main() { SServer server ; server.port = 3487;//  ushort -   cin.get()  ..    .    server.startServer(); return 0; }
      
      





そして、あなたがよく見たファイルには、.hが含まれます。 ここに彼は:



 #pragma once #pragma comment(lib, "ws2_32.lib") #pragma warning(disable: 4996) #include <iostream> #include <WinSock2.h> #include <winsock.h> #include "SClient.h" using namespace std;
      
      





結論:Habrに関する良い記事を読んだ後、C ++で簡単なTCPサーバーを作成する方法を学びました

UDPバージョンもありますが、違いは非常に小さく、すぐにここに来ると思います。



すべてがGitHubにあります



All Articles