Sock-04.とりあえず作るのTCP版
今回のお題
#Sock-01.とりあえず作る のTCP版
#Sock-03.基本的な流れ のフローチャートと見比べながら作るべし!
とりあえずTCP版をつくろう
Server
code:Server01.cpp
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment( lib, "ws2_32.lib" )
#include "DxLib.h"
// ポート番号
const unsigned short SERVER_PORT = 8888;
struct CIRCLE
{
int centerX;
int centerY;
int radius;
int color;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// WinSock2.2 初期化処理
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return -1;
}
// TCPリスンソケットの作成
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSock == INVALID_SOCKET)
{
return -1;
}
// lisntenSockをノンブロッキングモードに
unsigned long arg = 0x01;
if(ioctlsocket( listenSock, FIONBIO, &arg) == SOCKET_ERROR)
{
return -1;
}
// 固定アドレスの割り当て
SOCKADDR_IN bindSockAddress;
memset(&bindSockAddress, 0, sizeof(bindSockAddress));
bindSockAddress.sin_family = AF_INET;
bindSockAddress.sin_port = htons(SERVER_PORT);
bindSockAddress.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listenSock, (SOCKADDR*)&bindSockAddress, sizeof(bindSockAddress)) == SOCKET_ERROR)
{
return -1;
}
// リスン状態
if( listen( listenSock, 5 ) == SOCKET_ERROR )
{
return -1;
}
// DxLib周りの初期化・ウィンドウ作成処理
SetWindowText("サーバ!");
SetGraphMode(800, 600, 32);
ChangeWindowMode(TRUE);
if (DxLib_Init() == -1)
{
return -1;
}
SetBackgroundColor(0, 0, 0);
SetDrawScreen(DX_SCREEN_BACK);
SetAlwaysRunFlag(1);
// コネクション確立用ソケット
SOCKET sock = 0;
// クライアントのソケットアドレス
SOCKADDR_IN clientSockAddress;
int clientAddressLength = sizeof(clientSockAddress);
while (1)
{
ClearDrawScreen();
// 初期値...画面の範囲外
CIRCLE circle = { -100, -100, 0, GetColor(255, 255, 255) };
// コネクション確立前
if( sock < 1 )
{
sock = accept( listenSock,(SOCKADDR*)&clientSockAddress, &clientAddressLength );
if( sock != INVALID_SOCKET && WSAGetLastError() != WSAEWOULDBLOCK )
{
if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
{
return -1;
}
}
else
{
sock = 0;
}
}
else
{
// 受信
CIRCLE recvData;
SOCKADDR_IN clientAddr;
int clientAddressLength = sizeof(clientAddr);
int ret = recv(sock, (char*)&recvData, sizeof(recvData), 0);
// 受信時
if (ret > 0)
{
circle.centerX = ntohl(recvData.centerX);
circle.centerY = ntohl(recvData.centerY);
circle.radius = ntohl(recvData.radius);
circle.color = ntohl(recvData.color);
}
// 受信エラー 未受信時はWSAEWOULDBLOCKが発生
else if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// 受信失敗のエラー処理
}
}
// 描画
DrawCircle(circle.centerX, circle.centerY, circle.radius, circle.color, 1);
ScreenFlip();
WaitTimer(16);
if (ProcessMessage() == -1 || CheckHitKey(KEY_INPUT_ESCAPE) == 1)
{
break;
}
}
DxLib_End();
closesocket(listenSock);
WSACleanup();
return 0;
}
Client
code:Client01.cpp
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment( lib, "ws2_32.lib" )
#include "DxLib.h"
// サーバのIPアドレス
const char* SERVER_IPADDRESS = "127.0.0.1"; // とりあえず自分
// サーバのポート番号
const unsigned short SERVER_PORT = 8888;
struct CIRCLE
{
int centerX;
int centerY;
int radius;
int color;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// WinSock2.2 初期化処理
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return -1;
}
// TCPソケットの作成
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
return -1;
}
// サーバアドレスの指定
SOCKADDR_IN serverSockAddress;
memset(&serverSockAddress, 0, sizeof(serverSockAddress));
serverSockAddress.sin_family = AF_INET;
serverSockAddress.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, SERVER_IPADDRESS, &serverSockAddress.sin_addr.s_addr);
int serverAddressLength = sizeof(serverSockAddress);
// コネクション確立要求
if( connect( sock, (SOCKADDR*)&serverSockAddress, sizeof(serverSockAddress) ) == SOCKET_ERROR )
{
int ret = WSAGetLastError();
return -1;
}
// sockをノンブロッキングモードに
unsigned long arg = 0x01;
if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
{
return -1;
}
// DxLib周りの初期化・ウィンドウ作成処理
SetWindowText("クライアント");
SetGraphMode(800, 600, 32);
ChangeWindowMode(TRUE);
if (DxLib_Init() == -1)
{
return -1;
}
SetBackgroundColor(0, 0, 0);
SetDrawScreen(DX_SCREEN_BACK);
SetAlwaysRunFlag(1);
while (1)
{
ClearDrawScreen();
// サイズとか色はお任せ
CIRCLE circle = { 0, 0, 5, GetColor(0,255,255) };
// マウス座標取得し、circleのcenterXとcenterYに格納
GetMousePoint(&circle.centerX, &circle.centerY);
// 描画
DrawCircle(circle.centerX, circle.centerY, circle.radius, circle.color, 1);
// サーバ( serverAddr )に●の情報送信
CIRCLE sendData;
sendData.centerX = htonl(circle.centerX);
sendData.centerY = htonl(circle.centerY);
sendData.radius = htonl(circle.radius);
sendData.color = htonl(circle.color);
//
int ret = send(sock, (char*)&sendData, sizeof(sendData), 0 );
// 未送信以外のエラー
if (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
{
// エラー処理
}
ScreenFlip();
WaitTimer(16);
if (ProcessMessage() == -1 || CheckHitKey(KEY_INPUT_ESCAPE) == 1)
{
break;
}
}
DxLib_End();
closesocket(sock);
WSACleanup();
return 0;
}
なんとなく流れと、TCPはUDPよりコード量が増えていることがわかればよし
ちなみにTCPはコネクション確立型なので、このコードだと1:1通信
動作的にはUDPと同じはず
UDPサーバは複数のUDPクライアントから通信受け取れちゃうけど!
#ネットワーク関係
#ネットワークプログラミング