マルチスレッド同時サーバプログラミング

7159 ワード

マルチスレッド同時サーバプログラミング
一、実験目的
スレッドの作成と終了方法を理解する.
基本的なマルチスレッド同時サーバプログラムとクライアントプログラムの作成を学ぶ.
マルチスレッドとマルチプロセスの違いを理解します.
二、実験プラットフォーム
ubuntu-8.04オペレーティングシステム
三、実験内容
マルチスレッド同時サーバープログラムとクライアントプログラムを作成します.具体的な機能は以下の通りです.
1、サーバーは顧客の接続要求を受信するのを待ち、接続が成功すれば顧客アドレスを表示し、次にクライアントの名前を受信して表示する.次に、顧客からの文字列を受信し、1つの文字列を受信するたびに、その文字列を表示し、カエサルパスワードの暗号化方式(K=3)に従って文字列を暗号化し、暗号化された文字をクライアントに返す.その後、お客様が接続を閉じるまで、お客様の情報を受信するのを待ち続けます.複数のクライアント要求を同時に処理する能力がサーバに要求されます.
2、お客様はまず相応のサーバーと接続を確立する;次に、ユーザが入力したクライアント名を受信し、サーバに送信する.次に、ユーザーが入力した文字列を受信し続け、サーバに送信し、サーバから送信された暗号化された文字列を受信して表示します.その後、ユーザーがCtrl+Dを入力するまで、ユーザーが文字列を入力するのを待ち続け、お客様は接続を閉じて終了します.
四、実験原理
マルチプロセス方式forkを使用してサブプロセスを生成するにはいくつかの問題があります.まず、forkは大量のリソースを占有し、メモリイメージは親プロセスからサブプロセスにコピーされ、すべての記述子はサブプロセスでコピーされます.次にforkサブプロセスの後,プロセス間通信で親プロセスとサブプロセス間で情報を伝達する必要があり,サブプロセスから親プロセスに情報を返すには多くの作業が必要である.マルチスレッドは、上記の2つの問題を解決するのに役立ちます.
スレッドは、プロセス内の独立した実行エンティティとスケジューリングユニットであり、ライトレベルプロセスとも呼ばれます.スレッドの作成はプロセスより10~100倍速い.1つのプロセス内のすべてのスレッドは、同じメモリ領域、グローバル変数などの情報を共有します(このメカニズムは同期の問題をもたらします).
1、pthread_create()関数
pthread_create()関数は、新しいスレッドを作成するために使用されます.プログラムが実行を開始すると、システムは初期スレッドまたはメインスレッドと呼ばれる単一のスレッドを生成し、追加のスレッドはpthread_create()関数を作成します.
-------------------------------------------------------------------#include intpthread_create(pthread_t *tid, const pthread_attr_t *attr, void*(*func)(void *), void *arg); 戻る:成功した場合は0.エラーが発生した場合は0ではない--------------------------------------------------------------------------------------------------------------------
新しいスレッドはスレッドidによって識別されます:tid、新しいスレッドの属性attrには、優先度、初期スタックサイズ、デーモンスレッドであるべきかどうかなどが含まれます.スレッドの実行関数と呼び出しパラメータは、funcとargです.
スレッドの実行関数のパラメータと戻り値のタイプはvoid*であるため、任意のタイプを指すポインタを渡して返すことができます.
一般的な戻りエラー値:
EAGAIN:システムスレッド数の制限を超えています.
ENOMEN:新しいスレッドを生成するのに十分なメモリがありません.
EINVAL:無効な属性attr値です.
2、pthread_join()関数
pthread_join()関数は、スレッドの終了を待つために使用されます.
-------------------------------------------------------------------#inlcude intpthread_join(pthread_t tid, void **status); 戻る:成功した場合は0.エラーが発生した場合は正のエラーコードを返します.
この関数はwaitpid関数と似ていますが、パラメータtidで指定された待機スレッドのIDを指定する必要があります.この関数はいずれかのスレッドの終了を待つことはできません.
3、pthread_detach()関数
pthread_detach()関数は、指定したスレッドをオフにします.
-------------------------------------------------------------------#include intpthread_detach(pthread_t tid)は、成功した場合0を返します.エラー時にエラーコードを返します.
スレッドは合流可能(joinable)(デフォルト)、または離脱可能(detached).合流可能なスレッドが終了すると、スレッドidと終了状態は、別のスレッドがpthread_を呼び出すまで保持される.join.離脱したスレッドはデーモンプロセスのように、終了時にすべてのリソースを解放し、終了を待つことはできません.
パラメータtidは、オフに設定するスレッドIDを指定します.
4、pthread_self()関数
各スレッドにはIDがありますpthread_self()関数は、自分のスレッドIDを返します.
-------------------------------------------------------------------#include pthread_tpthread_self(void); 戻り:スレッドを呼び出すスレッドid----------------------------------------------------------------------------------------------------------
スレッドは、次の文を使用して、自分自身を離脱可能に設定できます.
pthread_detach(pthread_self());
5、pthread_exit()関数
pthread_exit()関数は、現在のスレッドを終了し、ステータス値を返すために使用されます.現在のスレッドが合流可能である場合、pthread_のためにスレッドidと終了ステータスが保持されます.join()関数呼び出し.
-------------------------------------------------------------------#include void pthread_exit(void*status); 戻り値なし;---------------------------------------------------------------------------------
ポインタstatus:スレッドの終了状態を指します.スレッドが終了すると、すべてのローカル変数が取り消されるため、ローカル変数を指すことはできません.
スレッドを終了させるには、次の2つの方法があります.
(1)スレッドを起動する関数pthread_create()の3番目のパラメータが返されます.その戻り値はスレッドの終了状態である.
(2)プロセスのmain()関数が返された場合、または現在のプロセスでexit()関数が呼び出された場合、プロセス内のすべてのスレッドが終了します.
五、実験手順
1、ubuntuオペレーティングシステムにログインし、mthread_という名前のファイルを新規作成するserver.c.
2、mthread_server.cでは、対応するコードを作成して保存し、サーバ側プログラムとして使用します.クライアントプログラムコードとmproc_client.c一致.blog:http://blog.csdn.net/yueguanghaidao/article/details/7060350
3、「端末」を開き、コマンドを実行してmthread_に入るserver.cとmproc_client.c所在ディレクトリ.
4、コマンドgccを実行する–omthread_servermthread_server.c-lpthread実行可能ファイルmthread_を生成server.
5、コマンドを実行する./mthread_サーバ、サーバ側を実行します.
6、第2の「端末」を開き、命令を実行してmthread_に入るserver.cとmproc_client.c所在ディレクトリ.
7、コマンドを実行する./mproc_client127.0.0.1、アナログ顧客1.
8、3番目の「端末」を開き、コマンドを実行してmthread_に入るserver.cとmproc_client.c所在ディレクトリ.
9、コマンドを実行します./mproc_client127.0.0.1、アナログ顧客2.
10、プログラムの実行結果は以下の通りである.
サーバ側:
お客様1:
お客様2:
11、クライアントでCtrl+Dを押し、クライアント接続を閉じる.
12、ソースコードを真剣に分析し、マルチスレッド同時サーバープログラムの作成を体得する.
六、参考プログラム(mthread_server.c)
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 1234
#define BACKLOG 5
#define MAXDATASIZE 1000

void process_cli(int connfd, struct sockaddr_in client);
void *function(void* arg);
struct ARG {
int connfd;
struct sockaddr_in client;
};

main()
{
int listenfd,connfd;
pthread_t  tid;
struct ARG *arg;
struct sockaddr_in server;
struct sockaddr_in client;
socklen_t  len;

if ((listenfd =socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Creatingsocket failed.");
exit(1);
}

int opt =SO_REUSEADDR;
setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr= htonl (INADDR_ANY);
if (bind(listenfd,(struct sockaddr *)&server, sizeof(server)) == -1) {
perror("Bind()error.");
exit(1);
}

if(listen(listenfd,BACKLOG)== -1){
perror("listen()error
"); exit(1); } len=sizeof(client); while(1) { if ((connfd =accept(listenfd,(struct sockaddr *)&client,&len))==-1) { perror("accept() error
"); exit(1); } arg = (struct ARG *)malloc(sizeof(struct ARG)); arg->connfd =connfd; memcpy((void*)&arg->client, &client, sizeof(client)); if(pthread_create(&tid, NULL, function, (void*)arg)) { perror("Pthread_create() error"); exit(1); } } close(listenfd); } void process_cli(int connfd, struct sockaddr_in client) { int num; char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE]; printf("Yougot a connection from %s.
",inet_ntoa(client.sin_addr) ); num = recv(connfd,cli_name, MAXDATASIZE,0); if (num == 0) { close(connfd); printf("Clientdisconnected.
"); return; } cli_name[num - 1] ='\0'; printf("Client'sname is %s.
",cli_name); while (num =recv(connfd, recvbuf, MAXDATASIZE,0)) { recvbuf[num] ='\0'; printf("Receivedclient( %s ) message: %s",cli_name, recvbuf); int i; for (i = 0; i ='a'&&recvbuf[i]<='z')||(recvbuf[i]>='A'&&recvbuf[i]<='Z')) { recvbuf[i]=recvbuf[i]+ 3; if((recvbuf[i]>'Z'&&recvbuf[i]<='Z'+3)||(recvbuf[i]>'z')) recvbuf[i]=recvbuf[i]- 26; } sendbuf[i] =recvbuf[i]; } sendbuf[num -1] = '\0'; send(connfd,sendbuf,strlen(sendbuf),0); } close(connfd); } void *function(void* arg) { struct ARG *info; info = (struct ARG*)arg; process_cli(info->connfd,info->client); free (arg); pthread_exit(NULL); }