センリュウのホームページへ ようこそ!
ネットワークプログラミング
inetd(あるいはxinetd)を使うとサーバーのプログラミングは格段に楽になるので、これを使ってみることにします。
実際上、クライアントからのコネクトを受け付け、子プロセスを作成するところまでinetd側でやってくれるので、子プロセスでのプログラミングだけでよくなります。
以下のプログラム例は、クライアントがオプションに1をつけて実行すると、サーバーは「answer1」を返し、2では「answer2」を、3では「answer3」を返すという簡単なものです。
●サーバー側
#include <sys/socket.h>
#include <stdio.h>
#include <string.h> /* strcpy */
#include <stdlib.h> /* atoi */
static char *lang[]={"ganswer1","hanswer2","hanswer3"};
int main()
{
size_t len;
struct sockaddr cl_addr;
int msqpro();
len=sizeof(cl_addr);
getpeername(0, &cl_addr, &len);
msqpro();
close(0);
exit(0);
}
//////////////////////////////////////////////////////////
int msqpro()
{
int index;
char buff[BUFSIZ];
if(read(0,buff,BUFSIZ) == -1)
{
perror("gserver: read");
return 1;
}
index=atoi(buff);
if(index == 0 || index > 3) strcpy(buff,"hinvalid index");
else strcpy(buff,lang[--index]);
if(write(0,buff,strlen(buff)+1) == -1)
{
perror("gserver: wtite");
return 1;
}
return 0;
}
inetdの設定
/etc/servicesに test 3000/tcp を追加(サービス名とポート/プロトコル。サービス名とポートは適宜)。
/etc/inetd.conf に test stream tcp nowait root /test/test test を追加(/test/testがプログラムだとする)。
/etc/hosts.allowに test: 192.168.0. (アクセスを許可するアドレスを適宜)。
xinetdの場合
/etc/xinetd.d/に以下のようなファイルを作って、xinetdサービスを再起動するだけでよい。
service test
{
id = test
socket_type = stream
protocol = tcp
wait = no
user = root
port = 3000
server = /test/test
only_from = 192.168.0.0/24 localhost
disable = no
}
●クライアント側
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#define PORT 3000
int main(int argc, char *argv[])
{
int sf;
struct sockaddr_in addr;
char buff[BUFSIZ];
if(argc < 2)
{
fprintf(stderr, "usage: %s index\n", basename(argv[0]));
return 1;
}
if((sf=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("client: socket");
return 1;
}
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr("192.168.0.1");
addr.sin_port=htons(PORT);
if(connect(sf, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
perror("client: connect");
return 1;
}
if(write(sf,argv[1],strlen(argv[1])+1) == -1)
{
perror("client: wtite");
return 1;
}
if(read(sf,buff,BUFSIZ) == -1)
{
perror("client: read");
return 1;
}
printf("data from server = %s\n", buff);
close(sf);
return 0;
}