接続プログラムの試作

図書館というものがあったことを思い出して,WinSock2の解説書を借りてきた.むやみに買う前に思い出せばよかった・・・

WinSock2プログラミング―Windows Sockets APIによるネットワークプログラミングのすべて

WinSock2プログラミング―Windows Sockets APIによるネットワークプログラミングのすべて

本を見ながら,コンソールからTCPでkgsGtpに接続するプログラムを書いてみた.GTPコマンドには問答無用で"?"を返すことにする.作ったソースはエントリの最後にくっつける.実行結果はこうなった.

ぎゃああああああ.
まず,recv()で受け取ったデータには終端文字列が付いていなかったようだ.そのせいで,前に受け取ったメッセージの残りとか,データが未定義の部分まで表示されている.終端文字列は確かGTPの仕様で使われていないので,ちゃんと処理しなければいけなかった.
そして,ログイン成功後,GTPコマンドが送信されてこないのでrecv()のところでずっとデータを待ち続け(ブロッキングと言うようだ),処理が帰ってこなくなった.危険すぎる.

別ルート(人用クライアント)で接続して,ログインまではできている事は確認した.(kgsGtp経由でログインすると名前の横にアイコンが付く)
さて,本に従って次はブロッキングが起きないような形にしていこう.

今回のコード

#include<stdio.h>
#include<winsock2.h>

int main(int argc, char **argv)
{
	WORD versionRequested = MAKEWORD(1,1);
	WSADATA dllWSAData;
	int ResultCode;

	/*ws2_32.dllの初期化*/
	ResultCode = WSAStartup(versionRequested,&dllWSAData);
	if(ResultCode != 0)
	{
		fprintf(stderr,"WSAStartup() error\n");
		WSACleanup();
		return 0;
	}

	/*WinSockのバージョンが要求と異なったら終了*/
	if(dllWSAData.wVersion != versionRequested)
	{
		fprintf(stderr,"requested version doesn't be supported\n");
		WSACleanup();
		return 0;
	}

	/*ソケットの作成と確認*/
	SOCKET sock_kgsGtp = socket(AF_INET,SOCK_STREAM,0);
	if(sock_kgsGtp == INVALID_SOCKET)
	{
		fprintf(stderr,"socket() failed\n");
		WSACleanup();
		return 0;
	}

	/*ソケットアドレスの設定*/
	struct in_addr addr_serv;
	addr_serv.s_addr=inet_addr("127.0.0.1");
	struct sockaddr_in sa_kgsGtp;
	sa_kgsGtp.sin_family = AF_INET;
	sa_kgsGtp.sin_port=htons(65535);
	sa_kgsGtp.sin_addr=addr_serv;

	/*kgsGtpへ接続*/
	ResultCode = connect(sock_kgsGtp,(LPSOCKADDR)&sa_kgsGtp,sizeof(SOCKADDR));
	if(ResultCode == SOCKET_ERROR)
	{
		fprintf(stderr,"connect error\n");
		WSACleanup();
		return 0;
	}


	/*GTPコマンドの受信と送信ループ*/

	char msg_recv[256];
	char msg_send[256];
	int flag_communicate = 1;
	while(flag_communicate == 1)
	{
		/* 9/13 ログイン成功後にコマンドが送られてこないのでrecv()で止まる*/
		recv(sock_kgsGtp,msg_recv,sizeof(msg_recv),0);
		fprintf(stdout,"%s\n",msg_recv);
		
		strcpy_s(msg_send,256,"?\n\n");
		send(sock_kgsGtp,msg_send,strlen(msg_send),0);
	}

	/*通信の終了*/
	shutdown(sock_kgsGtp,SD_BOTH);
	closesocket(sock_kgsGtp);
	WSACleanup();
	return 0;

}