つくろうとしています。
メインスレッドはaccept()し、サブスレッド(Thread2)で読み込み可能なソケットを
探し(GetReadableSock関数)、クライアントの相手をしています。
サブスレッドはクライアントからのデータをそのまま帰すだけです。
問題点はたくさんあると思いますが、主に2点です
・新しいクライアントが接続しても、先に接続していた他のクライアントが送信するまで
送信したデータを処理してくれない
→GetReadableSock()内でのselect関数が新しいソケットの面倒を見てくれない為だと思われる
→GetReadableSock()をどう変更した方がいいかわからない
・例えばクライアントが2人いた場合に、先に接続したクライアントが、切断すると
GetReadableSock()内のselect()がエラーを返す。
→切断したクライアントのソケットが登録されたままになっているためだと思われる
→GetReadableSock()内でINVALID_SOCKETを登録しないようにしてみましたが問題解決で
きませんでした
何か良い方法はあるでしょうか?
それとも根本からおかしいのでしょうか?
#include <stdio.h>
#include <conio.h>
#include <winsock2.h>
int nClient;
SOCKET ClientSock[10];
HANDLE hThread, hEvent;
//読み込み可能なソケットを返す
int GetReadableSock( unsigned int s[] ,int N)
{
int i;
fd_set fdset;
// fd_set変数を0に初期化する
FD_ZERO( &fdset );
// 各ソケットの番号を登録する
for( i=0; i<N; i++ ){
if(s[i]!=INVALID_SOCKET)FD_SET( s[i], &fdset ); //INVALID_SOCKETだったら登録しない・・・
}
// ソケット番号の最大値を探す
int max_s=0;
for( i=0; i<N; i++ ){
if( max_s < s[i] ) max_s = s[i];
}
// タイムアウトを10秒に設定
struct timeval tv;
tv.tv_sec = 7000;
tv.tv_usec = 0;
// ソケットにデータが届くまで待つ
int n = select( max_s+1, &fdset, NULL, NULL, &tv );
if( n == -1 ){ // 何らかのエラー
perror("select");
return -1;
}else if( n == 0 ){ // タイムアウト
fprintf( stderr, "select timeout\n" );
return 0;
}else if( n>0 ){ // どれかにデータが届いた
// どれが読み込み可能か検査
for( i=0; i<N; i++ ){
if( FD_ISSET( s[i], &fdset ) ){
return s[i]; // 読み込めるソケットを返す
}
}
return 0;
}
return 0;
}
DWORD WINAPI Thread2(LPVOID lpvoid ) {
char buf[4000];
int ret,n,i;
printf("ThreadOpened\n");
while(1){
WaitForSingleObject(hEvent,INFINITE);
SOCKET s=GetReadableSock(ClientSock,nClient);
printf("s=%d\n",s);
memset(buf,'\0',sizeof(buf));
ret=recv(s,buf,1024,0);
if(ret>0){
printf("%s\n",buf);
send(s,buf,ret,0);
}
if(ret==0){
closesocket(s);
nClient--;
s=INVALID_SOCKET;
if(nClient==0)ResetEvent(hEvent);
printf("nClient=%d\n",nClient);
}
}
ExitThread(TRUE);
}
int main(void)
{
WSADATA wsaData;
SOCKET ServSock,readable;
struct sockaddr_in addr;
struct sockaddr_in client;
struct sockaddr_in client2;
int len,i=0,ret;
char buf[1024],c;
DWORD dwParam1;
nClient=0;
WSAStartup(MAKEWORD(2,0), &wsaData);
ServSock= socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(5555);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
bind(ServSock, (struct sockaddr *)&addr, sizeof(addr));
printf("接続待ちです\n");
listen(ServSock, 10);
for(i=0;i<10;i++)ClientSock[i]=INVALID_SOCKET;
len = sizeof(client);
hThread=CreateThread(NULL , 0 , Thread2 ,NULL , CREATE_SUSPENDED , &dwParam1);
hEvent=CreateEvent(NULL, TRUE, FALSE, "EV01");
if(hEvent==NULL)MessageBox(NULL,"","",NULL);
ResumeThread(hThread);
while(nClient<10){
len = sizeof(client);
ClientSock[nClient] = accept(ServSock, (struct sockaddr *)&client, &len);
nClient++;
if(nClient==1)SetEvent(hEvent);
printf("Accepted=%d\n",nClient);
}
for(i=0;i<10;i++)closesocket(ClientSock[i]);
closesocket(ServSock);
WSACleanup();
return 0;
}