Winsockで明示的に接続を拒否したいのですが

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taketoshi
記事: 221
登録日時: 9年前
住所: 日本国

Winsockで明示的に接続を拒否したいのですが

#1

投稿記事 by taketoshi » 9年前

こんばんわ。お世話になります

TCPでWinsockを用いてサーバークライアントを構築しています。
一定数以上の接続は拒否してクライアント側にエラーコードを通知したいのですが上手くいきません。
明示的に、クライアントから来ているコネクション要求を破棄して、クライアント側にエラー通知を出すことは可能でしょうか?

サーバー側accept関数

コード:

////////////////////////////////////////////////////////////////////////
//接続許可を出す関数
//戻り値:int
////////////////////////////////////////////////////////////////////////
BOOL server::connectaccept(){
	SetCurret();
	char *lpStr;
	if(nConnectCount == DlgNetOption::nMaxConnect){
		lpStr = CastTimeStr("これ以上接続できません\r\n");
		SendMessage(hEdit,EM_REPLACESEL,1,(LPARAM)lpStr);
		accept(listen_s,NULL,0);				//ブロッキング回避の読み捨て
		return false;
	}else{
		nFromlen = sizeof(SOCKADDR_IN);
		for(i = 0;i <= DlgNetOption::nMaxConnect;++i){
				if(MemData[i].nId == 0){
					MemData[i].nId = i+1;
					MemData[i].s = accept(listen_s,(sockaddr *)&MemData[i].from,&nFromlen);
					if(MemData[i].s == INVALID_SOCKET){
						lpStr = CastTimeStr("接続ソケット生成エラー\r\n");
						SendMessage(hEdit,EM_REPLACESEL,1,(LPARAM)lpStr);
						return false;
					}else{
						++nConnectCount;
						wsprintf(szOutBuff,"%s",inet_ntoa(MemData[i].from.sin_addr));
						wsprintf(szInfoBuff,"%sが接続してきました\r\n",szOutBuff);
						lpStr = CastTimeStr(szInfoBuff);
						SendMessage(hEdit,EM_REPLACESEL,1,(LPARAM)lpStr);
						wsprintf(szInfoBuff,"接続台数:%d",nConnectCount);
						SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)szInfoBuff);
						return false;
					}
				}
			}
	}
	return true;
}
クライアント側コネクト通知

コード:

///////////////////////////////////////////////////////////////////
//FD_CONNECT
//
///////////////////////////////////////////////////////////////////
int client::Connect(LPARAM lParam){
	int nError;
	char szDebug[256];
	nError = WSAGETSELECTERROR(lParam);
	wsprintf(szDebug,"%d",nError);
		MessageBox(NULL,szDebug,"",MB_OK);
	if(WSAGETSELECTERROR(lParam) != 0){		//Connect関数のエラーコードを取得コレ重要 戻り値が0以外だとエラー
		MessageBox(NULL,"サーバーが見つかりません。設定を確認してください","エラー",MB_OK);
		SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)"接続待機中");
		client::SockFlag = FALSE;
		return -1;
	}else{
		SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)"サーバー接続中");
		client::SockFlag = true;
	}

	return 0;
}
以上のコードですと、最大接続数を超えての接続をサーバー側で弾いても
クライアント側ではWSAGETLASTERRORでもエラーコードが拾えず、クライアント側では接続が確立されている。と勘違いしてしまいます。


こういったシステムを作るときはエコーバックサーバーとしてやんわり断ってあげるのが正当なのでしょうか・・・・?
強制的に断る方法はもちろん、設計含め、ご教授ください。

アバター
shiro4ao
記事: 224
登録日時: 9年前
住所: 広島

Re: Winsockで明示的に接続を拒否したいのですが

#2

投稿記事 by shiro4ao » 9年前

「サービス提供用ソケット」+「接続拒否通知用ソケット」の接続まで受け入れてあげて、
クライアントがいっぱいの状態でもう一人がきたら、接続拒否用のソケットに
接続してもらって、その上で接続拒否をクライアントに伝えたほうが丁寧に思います。

詳しくないので何かうまい方法があったら申し訳ないです。
あくまで参考程度でお願いします。

アバター
Ciel
記事: 252
登録日時: 9年前

Re: Winsockで明示的に接続を拒否したいのですが

#3

投稿記事 by Ciel » 9年前

私なら、一回接続を受け入れて、
サーバ側からsendで特定の接続不可のメッセージをクライアント側に送って通知しますね。
その後サーバ側では、すぐ接続をきってやればよいと思います。

ど素人の意見ですので、あまり参考にしないほうがいいかも^^;
oui C'est la Vie♪

taketoshi
記事: 221
登録日時: 9年前
住所: 日本国

Re: Winsockで明示的に接続を拒否したいのですが

#4

投稿記事 by taketoshi » 9年前

おおおお、皆様ヒントをありがとうございます。
お二人の意見を参考に、切断用の別ソケットに接続して、
即効sendして即効シャットダウンすることで実現できました。

コード:

BOOL server::connectaccept(){
	SetCurret();
	char szBuff[256];
	char *lpStr;
	if(nConnectCount == DlgNetOption::nMaxConnect){
		lpStr = CastTimeStr("これ以上接続できません\r\n");
		SendMessage(hEdit,EM_REPLACESEL,1,(LPARAM)lpStr);
		s_down = accept(listen_s,NULL,0);				//切断用ソケットに接続
		strncpy(szBuff,"NO",sizeof(szBuff));
		send(s_down,szBuff,(int)strlen(szBuff),0);
		shutdown(s_down,SD_BOTH);
		closesocket(s_down);
		return false;
クライアント側はまだ手直ししていませんが、NOの文字列を読み取ってソレに見合った処理をすることで実現できそうです。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る