【linux下c言語サーバ開発シリーズ1】マルチプロセス処理マルチクライアントの接続
6941 ワード
上記では、非常に簡単なリターンサーバのdemoが提供されているが、このdemoの役割は非常に限られており、1つのクライアントの接続しか受信できず、その後、それと連絡を取り、通信を行うことができる.このクライアントが接続を切断してから、別の接続を処理することができます.機能が弱すぎます.マルチプロセスプログラムの設計を習ったことがあるので、複数のクライアントの接続を同時に処理できるように、ここではリターンサーバのマルチプロセスバージョンを提供します.
マルチプロセスは主にfork関数によって行われ、彼は特殊な関数であり、1回の呼び出し、2回の戻りである.戻り値が0より大きい場合は、親プロセスを表し、戻り値が子プロセスのpidを表します.戻り値が0に等しい場合は、サブプロセスであることを示します.サブプロセスは、親プロセスのコピーであり、親プロセスのすべてのものを保持します.しかし、サブプロセスに別の関数を実行させる必要があります.この関数は、プログラムに書いてサブプロセスで呼び出すことができます.既存のファイルでも、execファミリーの関数を使用して、サブプロセスの内容を複写することができます.この部分を具体的にどのように処理するかは、あなたのビジネスニーズを完全に見ています.この例では,既に受け入れられた接続に対して読み書き操作を行う.
返される親プロセスでは、プロセッサのメインフレームワークの内容を続行する必要があることがよくあります.また、サブプロセスのリソースを回収する必要があります.すなわち、サブプロセスの実行が完了するのを待って、waitとwaitpid関数でサブプロセスを回収し、ゾンビプロセスになってリソースを占有しないようにする必要があります.waitはサブプロセスの終了状態を返すことができ、waipidはブロックされていない処理を行うことができる.waitの補強版です.
次はこのバージョンのリターンサーバのdemoコードです.貼ってください.コードが再構築されていないため、乱れているように見えます.特に読み書き関数は,現在はまだばらばらな状態であり,抽出されていない.また,waitを行わないと引っかかりやすくなり,これは次に解決策を提供する.
このコードは、実行後、複数のtelnetでサーバに接続でき、サーバが複数のクライアントにサービスできることを発見します.コードに存在する欠点は、読み書き論理が悪い、サブプロセスの回収が行われていないなどで、次のバージョンで変更されます.また、マルチプロセスは一般的にプロセスプールを使用し、後のバージョンでも実装されます.お楽しみに.
マルチプロセスは主にfork関数によって行われ、彼は特殊な関数であり、1回の呼び出し、2回の戻りである.戻り値が0より大きい場合は、親プロセスを表し、戻り値が子プロセスのpidを表します.戻り値が0に等しい場合は、サブプロセスであることを示します.サブプロセスは、親プロセスのコピーであり、親プロセスのすべてのものを保持します.しかし、サブプロセスに別の関数を実行させる必要があります.この関数は、プログラムに書いてサブプロセスで呼び出すことができます.既存のファイルでも、execファミリーの関数を使用して、サブプロセスの内容を複写することができます.この部分を具体的にどのように処理するかは、あなたのビジネスニーズを完全に見ています.この例では,既に受け入れられた接続に対して読み書き操作を行う.
返される親プロセスでは、プロセッサのメインフレームワークの内容を続行する必要があることがよくあります.また、サブプロセスのリソースを回収する必要があります.すなわち、サブプロセスの実行が完了するのを待って、waitとwaitpid関数でサブプロセスを回収し、ゾンビプロセスになってリソースを占有しないようにする必要があります.waitはサブプロセスの終了状態を返すことができ、waipidはブロックされていない処理を行うことができる.waitの補強版です.
次はこのバージョンのリターンサーバのdemoコードです.貼ってください.コードが再構築されていないため、乱れているように見えます.特に読み書き関数は,現在はまだばらばらな状態であり,抽出されていない.また,waitを行わないと引っかかりやすくなり,これは次に解決策を提供する.
#include"head.h"
#define MAX_USER 1024
#define BUF_SIZE 1024
typedef struct user //yon {
int conn; //
sockaddr_in client_addr; //
char bufread[BUF_SIZE]; //
char bufwrite[BUF_SIZE]; //
} user;
int main(int argc, char **argv)
{
if(argc<3)
{
printf("usage: %s ip port
",basename(argv[0]));
exit(0);
}
printf("start echoback server...
");
char * ip=(char * ) argv[1];
int port =atoi(argv[2]);
/* , sockaddr_in */
struct sockaddr_in server_address;
bzero(&server_address,sizeof(server_address));
server_address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&server_address.sin_addr);
server_address.sin_port=htons(port);
int listenfd=socket(AF_INET,SOCK_STREAM,0);
assert(listenfd>=0);
int reuse=1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
setnonblock(listenfd);
int ret=bind(listenfd,(struct sockaddr *) &server_address, sizeof(server_address));
assert(ret==0);
ret=listen(listenfd,5);
assert(ret==0);
/* , */
int run_flag=1;
char buf[1024];
int conn=-1;
user users[MAX_USER];
int stop[MAX_USER];
for(int i=0;i<MAX_USER;i++)
stop[i]=0;
int user_number=0;
while(run_flag)
{
int acfd=accept(listenfd,NULL,NULL);
if(acfd>=0)
{
printf("acfd>0,hhahahaha");
user_number++;
/*users[user_number] conn, */
users[user_number].conn=acfd;
pid_t pid=fork();
if(pid<0)
{
printf("fork error
");
exit(0);
}
else if (pid==0) /* */
{
close(listenfd); // ,
setnonblock(users[user_number].conn);
//while(!stop[ users[user_number].conn] )
while(1)
{
int readn=read(users[user_number].conn,users[user_number].bufread,BUF_SIZE);
// printf("readn=%d
",readn);
//printf("errno=%d
",errno);
if( (readn<0) && (errno!=EAGAIN))
{
printf("a
");
printf("read fail, client %d
",users[user_number].conn);
close(users[user_number].conn);
//stop[ users[user_number].conn ]=1;
//break;
exit(0);
}
else if (readn==0)
{
printf("b
");
close(users[user_number].conn);
//stop[ users[user_number].conn ]=1;
//break;
exit(0);
} else if (readn>0)
{
printf("pid= %d
",getpid());
users[user_number].bufread[readn]='\0';
memcpy(users[user_number].bufwrite,users[user_number].bufread,sizeof(users[user_number].bufread));
int writen=write(users[user_number].conn,users[user_number].bufwrite,sizeof(users[user_number].bufwrite));
memset(users[user_number].bufread,0,sizeof(users[user_number].bufread));
printf("write %d bytes to %d
",writen,users[user_number].conn);
}
}
}
/*parent process*/
else
{
close(users[user_number].conn);
int stat_loc;
/* , , sigchld */
// wait((int *)&stat_loc);
printf("parent, finished wait
");
}
}
}
}
このコードは、実行後、複数のtelnetでサーバに接続でき、サーバが複数のクライアントにサービスできることを発見します.コードに存在する欠点は、読み書き論理が悪い、サブプロセスの回収が行われていないなどで、次のバージョンで変更されます.また、マルチプロセスは一般的にプロセスプールを使用し、後のバージョンでも実装されます.お楽しみに.