いろんなものはつながっている

ネットワークプログラミング基礎 チャット

「猫でもわかるネットワークプログラミング」で例としてあげれらていたチャット機能はウィンドウを用いたものであったがコンソールでの簡易的なチャット機能をつくってみることにした。

チャット機能なので受信と送信を非同期にできるようにしないといけない。非同期を実現するのに、「猫でもわかる~」ではWSAAsyncSelectを用いて受信用のプロシージャを定義していた。今回はコンソールでつくろうと思うので、受信用のスレッドをつくって受信することにした。

受信用のスレッドプロシージャrecvThread(void* pRecvSocket)を定義して、そのプロシージャ内で接続をlistenし接続をacceptしたらそのソケットを使って相手からのメッセージを受信している。

接続先IPやポートはベタ書きだしエラー処理も全くしていないけど、動作することは確認できた。

// チャット
//

#include "stdafx.h"

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

#include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h>

#define RECV_PORT 9876
#define SEND_PORT 9875

#define BUFFER_SIZE 1024

bool bRecv = true;

// 受信用
unsigned __stdcall recvThread(void* pRecvSocket)
{
	int nSocket = *((int*)pRecvSocket);

  	// コネクションの受付を開始
	listen(nSocket, 1);
	
	// コネクションを受け付ける
	struct sockaddr_in ClientAddr;
	int nClientAddrSize = sizeof(ClientAddr);
	int nConnectedSocket = accept(nSocket, (struct sockaddr*)&ClientAddr, &nClientAddrSize);
	_tprintf(_T("%s から接続を受けました\n"), inet_ntoa(ClientAddr.sin_addr));

	TCHAR szBuf[BUFFER_SIZE];
	while(bRecv){
		memset(szBuf, 0, sizeof(szBuf));
		int nMsgSize = recv(nConnectedSocket, szBuf, sizeof(szBuf), 0);
		if(nMsgSize == 0) break;
		_tprintf(_T("YOU: %s\n"), szBuf);
	}

	closesocket(nConnectedSocket);
  
	return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
	// WinSockの初期化
	WSADATA data;
	WSAStartup(MAKEWORD(2,0), &data);

	// 受信用ソケットの生成
	int nMeSocket = socket(AF_INET, SOCK_STREAM, 0);

	// 受信用IP,ポート番号の設定
	struct sockaddr_in MeAddr;
	memset(&MeAddr, 0, sizeof(MeAddr));
	MeAddr.sin_port = htons(RECV_PORT);
	MeAddr.sin_family = AF_INET;
	MeAddr.sin_addr.s_addr = htonl(INADDR_ANY);//どのIPアドレスからでも接続を受け付ける
	bind(nMeSocket, (struct sockaddr*)&MeAddr, sizeof(MeAddr));

	// 受信用スレッド
	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, recvThread, &nMeSocket, 0, NULL);

	// 送信用の作成ソケット
	int nYouSocket = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in YouAddr;
	memset(&YouAddr, 0, sizeof(YouAddr));
	YouAddr.sin_port = htons(SEND_PORT);
	YouAddr.sin_family = AF_INET;
	YouAddr.sin_addr.s_addr = inet_addr(_T("192.168.11.6"));

  	// コネクションを確立
	_tprintf(_T("接続中...\n"));
	while(1){
		if(!connect(nYouSocket, (struct sockaddr*)&YouAddr, sizeof(YouAddr))){
			_tprintf(_T("接続しました\n"));
			break;
		}
	}

	TCHAR szBuffer[BUFFER_SIZE];
	while(1){
		memset(szBuffer, _T('\0'), sizeof(szBuffer));
		scanf(_T("%s"), &szBuffer);	
		send(nYouSocket, szBuffer, BUFFER_SIZE, 0);
		if(_tcscmp(szBuffer, _T("quit")) == 0){
			bRecv = false;
			break;
		}
	}

	closesocket(nYouSocket);
	closesocket(nMeSocket);

	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread); 

	WSACleanup();

	return 0;

}

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

スポンサード リンク

カテゴリー

スポンサード リンク