ページ 1 / 1
マルチスレッドのサーバー作り
Posted: 2010年8月13日(金) 21:41
by スモモ
[1] 質問文
[1.1] 自分が今マルチプロセッサのサーバー作りたいです。
[1.2] 取り組んだプログラムコードが下にあります。
[1.3] 複数クライアント対応作るつもりですが複数対応なってないです。
[1.4] どうすれば複数クライアントが扱えるサーバーがどのように作ればいいでしょうか?
[2] 環境
[2.1] OS : Windows
[2.2] コンパイラ名 : VC++ 2008
[3] その他
・C言語を一年半ぐらい勉強しました。初級か中級ぐらいです。
・ライブラリを使っていません。
#include <process.h>
#include <winsock2.h>
#pragma comment(lib,"WSOCK32")
#pragma warning(disable:4312)
class C_server{
int dstSocket;
static void CallFunc( LPVOID pParam );
public:
C_server(int dstSocket);
void MainFunc();
};
C_server::C_server(int dstSocket):dstSocket(dstSocket){_beginthread(CallFunc,0,this);}
void C_server::CallFunc(LPVOID pParam){((C_server*)pParam)->MainFunc();}
void C_server::MainFunc(){
char buffer[1024];
while(dstSocket){
//パケットの受信
int numrcv = recv(dstSocket, buffer, sizeof(char)*1024, 0);
if(numrcv ==0 || numrcv ==-1){
closesocket(dstSocket);
break;
}
printf("変換前 %s",buffer);
for (int i=0; i< numrcv; i++){ // bufの中の小文字を大文字に変換
buffer = toupper(buffer);
}
// パケットの送信
send(dstSocket, buffer, sizeof(char)*1024, 0);
printf("→ 変換後 %s \n",buffer);
}
}
void main()
{
// ポート番号,ソケット
int srcSocket; // 自分
int dstSocket; // 相手
// sockaddr_in 構造体
struct sockaddr_in srcAddr;
// Windows の場合
WSADATA data;
WSAStartup(MAKEWORD(2,0), &data);
// sockaddr_in 構造体のセット
memset(&srcAddr, 0, sizeof(srcAddr));
srcAddr.sin_port = htons(40453);
srcAddr.sin_family = AF_INET;
srcAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// ソケットの生成(ストリーム型)
srcSocket = socket(AF_INET, SOCK_STREAM, 0);
// ソケットのバインド
bind(srcSocket, (struct sockaddr *) &srcAddr, sizeof(srcAddr));
// 接続の許可
listen(srcSocket, 10);
while(1){
if((dstSocket = accept(srcSocket, NULL, 0))>0){
//static C_server s(dstSocket); //
new C_server(dstSocket); //
//C_server s(dstSocket); //
}
}
WSACleanup();
}
ご教授の程、よろしくお願いします。 
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月13日(金) 22:12
by Poco
マルチスレッドプログラミングになります。
accept()後にスレッドを生成し、それにdstSocketを渡してください。
#タイトルから判断するに、マルチプロセスで処理したいようにも
#見えますが、Windowsってできましたっけ?
#不可能か、結構面倒だったので諦めた覚えがあります。

Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 17:59
by スモモ
ぽこさん
ご回答ありがとうございます。
> accept()後にスレッドを生成し、それにdstSocketを渡してください。
おっしゃる通りやっていると思いますが、よくわからないです。
よければ、詳しく教えていただけないでしょうか。
> #タイトルから判断するに、マルチプロセスで処理したいようにも
> #見えますが、Windowsってできましたっけ?
> #不可能か、結構面倒だったので諦めた覚えがあります。
よくわからないです。
わかるまで、マルチスレッドプログラミングとして覚えます。
ご指摘いただき、ありがとうございました。
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 18:21
by softya
大雑把に説明しますね。
サーバー処理は、通用マルチスレッドあるいはマルチプロセスで処理します。これは、マルチプロセッサ(マルチコア含む)であることとは無関係です。
サーバーとクライアントが通信待ちしている間CPUは事実上Sleep状態になっていてCPUパワーの資源は無駄に使われていない状態と言えます。そこで、その無駄な時間を出来るだけ減らすために同時に復数のクライアントと通信をするための工夫がマルチスレッドあるいはマルチプロセスです。
ちなみにスモモさんのコードはマルチスレッドやマルチプロセスは一切行われていません。
有名なApache HTTP Serverの動作が書かれています。
http://ja.wikipedia.org/wiki/Apache_HTTP_Server
まず、マルチプロセスやマルチスレッドに付いて学ばれてはどうでしょう。
※ マルチプロセッサの負荷分散に付いてはOS任せにするのが一番です。マルチプロセスやマルチスレッドを使えば自動的にプロセッサを振り分けてくれますので気にしなくて良いです。
マルチプロセスの例。ただし、この人はスレッドの方が良いと言ってますが。
http://abtc.cocolog-nifty.com/tips/2005 ... _f286.html
TCP/IP通信 _beginthreadexでスレッドを使用。
http://7ujm.net/C++/SDKTCP.html
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 19:39
by スモモ
softyaさん
ご丁寧に説明いただきありがとうございます。
それなのに、少ししかわからなくでごめんなさい!
もっと勉強する必要と思いますが。
とりあえず、クライアント50ぐらい同時に処理できるサーバーが作りたいです。
アドバイス参照しながら、やっていきます。
もし、よければ、もっとアドバイス下さい。
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 19:53
by softya
アドバイスはOKですが、何が分からないか整理してもらえますか。
>それなのに、少ししかわからなくでごめんなさい!
何がわかって、何が自分で調べても理解できなかったかできるだけ細かく整理出来ていると説明ポイントが絞りやすく良いですね。
マルチスレッドについて詳しく説明しようと思ったら、OS全般のことを説明することになり内容が本一冊分ってこともありえます。なので、とてもここで説明しきれませんので本を紹介することになると思います。
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 20:10
by dic
>マルチプロセッサ
まずはこの単語の意味から調べてください
次にWindowsのCPUの使われ方を調べてください
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 20:27
by スモモ
softyaさん
ご親切にしてもらってありがとうございます。
> >それなのに、少ししかわからなくでごめんなさい!
の意味は
したいことを聞いたら、したいことだけでなく、他にも理解しないといけないことが多くなりました。
すべてを学ぶのは時間かかることと、
自分、時間がないと自分をどうしようもないところを追い詰めたことだと思います。
自分が未熟のせいです。
softyaさんは気にしないでください。
よかったら、自分が書いたコード(上にあります)見てもらってもいいでしょうか。
なぜ、クライアント1つしか処理できない教えてもらってもいいでしょうか。
Re:マルチプロセッサのサーバー作り
Posted: 2010年8月14日(土) 20:38
by Poco
> なぜ、クライアント1つしか処理できない教えてもらってもいいでしょうか。
accept()の後、つまりユーザから接続を受けた後から C_serverクラスのコンストラクタ内の処理の間、
ユーザから接続を待っていないからです。
並列に処理を行ないたいのなら、ユーザからの接続を受けた後、スレッドを作成し、
すぐに接続待ち(accept()呼び出し)に戻る必要があります。
生成されたスレッドの中で、C_serverクラスのコンストラクタ内の処理相当のことをすれば、OKです。
Re:マルチスレッドのサーバー作り
Posted: 2010年8月14日(土) 20:39
by スモモ
dicさん
書き込みありがとうございました。
> >マルチプロセッサ
> まずはこの単語の意味から調べてください
> 次にWindowsのCPUの使われ方を調べてください
お恥ずかしいところ見せちゃってすいません。
調べてみます。
Re:マルチスレッドのサーバー作り
Posted: 2010年8月14日(土) 20:44
by スモモ
ぽこさん
ご親切に回答してもらって、ありがとうございます。
コード書き直してみます。
Re:マルチスレッドのサーバー作り
Posted: 2010年8月14日(土) 23:02
by dic
配列は扱えますか?
//=======================================================
Windowsで動くソースは持ってますし、動作の確認もできました
運営したいのですが、時間の都合上できない状態です
ちなみに私の持っているソースはサーバ側はシングルスレッドで処理してます
ネット上の知り合いになりますが、20~30人接続してもラグが発生しないようです
なかなか知名度が低く、これ以上のクライアント(ユーザ)を確保できないので
性能の指標は未知数です
Re:マルチスレッドのサーバー作り
Posted: 2010年8月15日(日) 10:46
by Poco
> 配列は扱えますか?
>
> ちなみに私の持っているソースはサーバ側はシングルスレッドで処理してます
> ネット上の知り合いになりますが、20~30人接続してもラグが発生しないようです
selectやpollを使っているんですか?
Re:マルチスレッドのサーバー作り
Posted: 2010年8月15日(日) 13:45
by dic
>selectやpollを使っているんですか?
ソケット通信までとしか都合上言えないです
Re:マルチスレッドのサーバー作り
Posted: 2010年8月15日(日) 19:32
by スモモ
みなさん
ご協力ありがとうございます。
自分もよくわからないですが、できました。みなさんのおかげです。
いろいろやってみたら、上のコードとほとんど変わらないですが、できるようになりました。
どなた、わかっている方、ご教授の程、よろしくお願いします。
コードは以下のようになります。
/*
S/2010/08/03 ServerTest00.h
E/2010/08/15 ServerTest23.h
*/
#include <stdio.h>
#include <process.h>
#include <winsock2.h>
#pragma comment(lib,"WSOCK32")
#define MAX 3
#define PORT 1234
//
class C_server{
int dstSocket; // 相手
char *name;
static void CallFunc( LPVOID pParam );
public:
static int cnt;
C_server();
C_server(int dstSocket,char *name);
void step();
};
int C_server::cnt = 0;
C_server::C_server(){dstSocket = 0;}
C_server::C_server(int dstSocket,char *name):dstSocket(dstSocket),name(name){_beginthread(CallFunc,0,this);}
void C_server::CallFunc(LPVOID pParam){((C_server*)pParam)->step();}
void C_server::step(){
char buffer[1024];
cnt++;
int NO = cnt;
printf("%d 個クライアントが接続している\n",cnt);
while(1){
//パケットの受信
int numrcv = recv(dstSocket, buffer, sizeof(char)*1024, 0);
if(numrcv ==0 || numrcv ==-1){
closesocket(dstSocket);
cnt--;
printf("NO.%d 接続切れた %d 個クライアントが接続している\n",NO,cnt);
break;
}
printf("NO.%d %s 変換前 %s",NO,name,buffer);
for (int i=0; i< numrcv; i++){ // bufの中の小文字を大文字に変換
buffer = toupper(buffer);
}
// パケットの送信
send(dstSocket, buffer, sizeof(char)*1024, 0);
printf("→ 変換後 %s \n",buffer);
}
}
//
void main()
{
// ポート番号,ソケット
int srcSocket; // 自分
int dstSocket; // 相手
// sockaddr_in 構造体
struct sockaddr_in srcAddr;
struct sockaddr_in dstAddr;
// Windows の場合
WSADATA data;
WSAStartup(MAKEWORD(2,0), &data);
// sockaddr_in 構造体のセット
memset(&srcAddr, 0, sizeof(srcAddr));
srcAddr.sin_port = htons(PROT);
srcAddr.sin_family = AF_INET;
srcAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// ソケットの生成(ストリーム型)
srcSocket = socket(AF_INET, SOCK_STREAM, 0);
// ソケットのバインド
bind(srcSocket, (struct sockaddr *) &srcAddr, sizeof(srcAddr));
// 接続の許可
listen(srcSocket, MAX + 1/*(int)0x8ffffff*//*1*/);
while(1){
int dstAddrsize = sizeof(dstAddr);
// 接続の受付け
printf("接続を待っています\nクライアントプログラムを動かしてください\n");
if((dstSocket = accept(srcSocket, (struct sockaddr *) &dstAddr, &dstAddrsize))>0){
if(C_server::cnt >= MAX){
printf("接続最大数 %d を超えた\n",MAX);
continue;
}
printf("%s から接続を受けました\n", inet_ntoa(dstAddr.sin_addr));
new C_server(dstSocket,inet_ntoa(dstAddr.sin_addr)); //
}
}
WSACleanup();
}
ご教授の程、よろしくお願いします。
Re:マルチスレッドのサーバー作り
Posted: 2010年8月15日(日) 22:29
by dic
新手の釣りでしょうか?
Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 14:04
by スモモ
dicさん
書き込みありがとうございます。
> 新手の釣りでしょうか?
の意味わからないですが、教えていただけないでしょうか?
Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 14:21
by softya
まったくスレッドを使っていないので絶対に目的が達成されていないのに「できました」と書かれていたからだと思います。スレッドを使っていないのはなぜでしょうか?
それと時間がないのに、こんなに悠長にしていて大丈夫ですか?

Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 18:07
by Coca
C++を使用したことがないので、質問になりますが、
メインスレッド内、newで確保した領域を解放する必要があると思いますが、その点は問題ありませんか?
後は定型文みたいなものですから、_beginthreadの運用としてはいいのではないでしょうか。
_beginthreadのせいと思わしき問題が出るけど、俺のテスト項目のことだから、まぁいっかw

Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 19:19
by Poco
> softyaさん
> まったくスレッドを使っていないので絶対に目的が達成されていないのに
一応コンストラクタの所で_beginthread()を呼び出していますよ。
>スモモさん
やりたいことは達成出来たのですよね?
他に何が問題/疑問なのでしょうか?
Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 19:43
by softya
>一応コンストラクタの所で_beginthread()を呼び出していますよ。
失礼しました。
じゃあ。問題ないはずですからテストをして問題ないことを確認してくださいとしか言えません。
Re:マルチスレッドのサーバー作り
Posted: 2010年8月16日(月) 21:11
by スモモ
みなさん
ご協力ありがとうございます。
おかげで解決しました。
またよろしくお願いします。