サーバーソケット

■サーバーソケット

サーバーソケットはデータ受信側のソケットです。
送信側がいつ通信を行うか分からないので、
常に起動してクライアントから通信要求が来るのを待っています。
この待機状態のことをリスン(listen)状態と呼びます。

●作成手順(同期通信)
	①.ポート番号の設定
		このサーバーで使用するポート番号の設定をする

	②.WinSockの初期化
		WSAStartup関数でWinSockを初期化します。

	③.ソケットを開く
		socket関数でソケットをオープンします。

	④.ソケットとポートを関連付ける
		bind関数でソケットにポートとIPアドレスの関連付けを行います。

	⑤.ソケットを待機状態にする
		listen関数でソケットを待機状態にしてクライアントから通信を待ちます。

	⑥.クライアントからの接続を受けいれる
		accept関数でクライアントからの接続を受け入れて
		新しいコネクションを作成します。

		通信可能な新しいソケット:
			accept関数が実行されるとサーバーとクライアント間で
			通信可能なソケットが返され、手順、⑦と⑧は
			このソケットを使用して行います。

	⑦.データを受信する
		recv関数でクライアントからのデータを受信します。

	⑧.ソケットの送受信を停止する
		shutdown関数でソケットの送受信を停止します。

	⑨.ソケットを閉じる
		closesocket関数でソケットを閉じます。

	⑩.WinSockを終了する
		WSACleanup関数でWinSockを終了します

●コード
	#define _WINSOCK_DEPRECATED_NO_WARNINGS
	#include <stdio.h>
	#include <WinSock2.h>

	#pragma comment(lib, "Ws2_32.lib")

	void main(void)
	{
		WSADATA wsa_data;

		SOCKET server_socket;
		char buff[1024];
		unsigned short port_no = 0;
		SOCKADDR_IN sock_addr_in;

		// ①ポート番号の設定
		printf("--------ポート番号--------\n");
		gets_s(buff);
		port_no = atoi(buff);

		// ②WinSock初期化
		if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
		{
			printf("WinSock初期化に失敗しました\n");
			getchar();
			return;
		}

		// ③ソケット作成
		server_socket = socket(AF_INET, SOCK_STREAM, 0);
		if (server_socket < 0)
		{
			printf("ソケットオープンエラー\n");
			getchar();
			WSACleanup();
			return;
		}

		// ④ソケットとポートの結びつけ
		memset(&sock_addr_in, 0, sizeof(SOCKADDR_IN));
		sock_addr_in.sin_family = AF_INET;
		sock_addr_in.sin_port = htons(port_no);
		sock_addr_in.sin_addr.s_addr = INADDR_ANY;
		if (bind(server_socket, (SOCKADDR*)&sock_addr_in, sizeof(sock_addr_in)) ==
										SOCKET_ERROR)
		{
			printf("バインドエラー\n");
			getchar();
			closesocket(server_socket);
			WSACleanup();
			return;
		}

		// ⑤ソケットを待機状態に変更
		if (listen(server_socket, 0) == SOCKET_ERROR)
		{
			printf("待機状態変更失敗\n");
			getchar();
			closesocket(server_socket);
			WSACleanup();
			return;
		}

		SOCKADDR_IN from;
		int from_len = sizeof(from);
		SOCKET accept_socket;

		// ⑥クライアントから接続受け入れ
		accept_socket = accept(server_socket, (SOCKADDR*)&from, &from_len);
		if (accept_socket == INVALID_SOCKET)
		{
			printf("accept error\n");
			closesocket(server_socket);
			WSACleanup();
			return;
		}

		printf("%sが接続してきました\n", inet_ntoa(from.sin_addr));
		printf("受信を開始します\n終了は end です");
		while (true)
		{
			// ⑦データ受信
			int result = recv(accept_socket, buff, sizeof(buff) - 1, 0);
			if (result == SOCKET_ERROR)
			{
				printf("受信エラーです\n");
				break;
			}

			buff[result] = '\0';
			
			if (strcmp(buff, "end") == 0)
			{
				printf("クライアントが接続を切りました\n");
				break;
			}
			printf("受信----%s\n", buff);
		}

		// ⑧ソケットの送受信停止
		shutdown(accept_socket, SD_BOTH);
		// ⑨ソケットを閉じる
		closesocket(accept_socket);
		closesocket(server_socket);
		// ⑩WinSock終了
		WSACleanup();
	}