2007年8月31日金曜日

echoサーバ




#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#define MAX 5
#define RCVSIZE 32

void errorExit(char *message);
void Handling(int clntSocket);


int main(int argc,char *argv[])
{
int servSocket;
int clntSocket;
struct sockaddr_in echoServAddr;
struct sockaddr_in echoClntAddr;
unsigned short echoServPort;
unsigned int clntLen;

if(argc != 2){
fprintf(stderr,"Usage: %s <Port>\n",argv[0]);
exit(1);
}

echoServPort = atoi(argv[1]);

if((servSocket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
errorExit("socket error\n");

memset(&echoServAddr,0,sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);

if(bind(servSocket,(struct sockaddr *) &echoServAddr,sizeof(echoServAddr)) < 0)
errorExit("bind error\n");

if(listen(servSocket,MAX) < 0)
errorExit("listen error\n");

for(;;){

clntLen = sizeof(echoClntAddr);

if((clntSocket = accept(servSocket,(struct sockaddr *) &echoClntAddr,&clntLen)) < 0)
errorExit("accept error\n");

printf("Handling client %s\n",inet_ntoa(echoClntAddr.sin_addr));

Handling(clntSocket);
}


}

void Handling(int clntSocket)
{
char echoBuffer[RCVSIZE];
int recvMesSize;


if((recvMesSize = recv(clntSocket,echoBuffer,RCVSIZE,0)) < 0)
errorExit("recv error\n");

while(recvMesSize > 0)
{
if(send(clntSocket,echoBuffer,recvMesSize,0) != recvMesSize)
errorExit("send error\n");

if((recvMesSize = recv(clntSocket,echoBuffer,RCVSIZE,0)) < 0)
errorExit("recv error\n");
}

close(clntSocket);
}



関数名、変数名を付けるセンスがないって気づいてしまった。。。。





socket関連の関数のメモ2



manページ書き写してるだけなんで気にしないでください。






  • man 2 bind


int bind(int sockfd,const struct *sockaddr,socklen_t addr_len)


サーバのソケットにローカルのアドレス等を割り当てる


sockfd


ソケットのディスクリプタ


*sockaddr


サーバのアドレス、ポート、アドレスファミリの構造体



addr_len


構造体のサイズ


戻り値は成功時に0、それ以外は-1







  • man 2 listen


int listen(int sockfd,int backlog)


ソケットを接続待ちの状態にする


sockfd


ソケットのディスクリプタ


backlog


同時接続最大数


戻り値は成功時に0、それ以外は-1












  • man 2 accept


int accept(int sockfd,struct *sockaddr,socklen_t *addrlen)


ソケットへの接続を受け付ける


sockfd


ソケットのディスクリプタ


*sockaddr


クライアントのアドレスが入る


*addrlen


sockaddrのサイズが入る


戻り値はアドレスのサイズ(バイト単位)









  • inet_ntoa()


ドット10進数のIPアドレスを32bit2進数に変換する。






  • inet_addr()


32bit2進数表記のIPアドレスをドット10進数に変換する。





subversionのインストール



Plamoのcontribには、subversionのパッケージがあるんだけど、実行するとlibaprutil-0.so.0が見つからないって怒られます。


libaprutilを調べてみるとapache関係みたいで、apacheを入れないといけないみたい。


subversionを入れたいだけなのに、apachまで入れるのは、ちょっと。。。。


ってことで、libaprとlibaprutilをmakeして入れました。



  • 1.apr.apacheからダウンローする。1.*系列と0.*系列があるけれど、plamoでは0.*系列の方が必要

  • 2.それぞれ解凍して./configure && make && make install でOK


でも、subversion入れるのにapacheが必要って普通なの?それとも探し方が悪かっただけで、本当は別のパッケージがあったのかな?





2007年8月29日水曜日

socket関連の関数のメモ







  • man 2 socket


int socket(int domain,int type,int protocol)


ソケットを作って、そのソケットのディスクリプタを返す。


domain


プロトコルファミリの指定


PF_INET IPv4


PF_INET6 IPv6


などがある。とりあえず今のところは、PF_INETしか使わないと思う。


type


通信方法の指定


SOCK_STREAM


SOCK_DGRAM


などがある。色々とあるが、とりあえずこの2つしか使わないと思う。





protocol


そのソケットが利用するプロトコルを指定する。


戻り値は、ソケットのディスクリプタ、エラーの場合には-1









  • man 2 connect


int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addr_len)


ディスクリプタsockfdが参照するソケットを*serv_addrのアドレスに接続する。


sockfd


接続するソケットのディスクリプタ





*serv_addr


接続先のIPアドレス、ポート番号等を指定する。





addr


serv_addrのサイズを指定する。


socketlen_tとなっているが実際にはint。


戻り値


成功時は、0。失敗したときは、-1









  • man 2 send


ssize_t send(int s,const void *buf,size_t len,int flags)


ソケットにメッセージを送る。


s


ソケットのディスクリプタ


*buf


送信したいメッセージのポインタ


len


送信したいメッセージのサイズ


flags


send()が呼び出されたときのプログラムの振舞を決める。


man を読んでも良く理解できない。0でデフォルトになる。


戻り値


成功時は、送信したメッセージのサイズ。失敗したときは、-1







  • man 3 recv


ssize_t recv(int s,void *buf,size_t len,int flags)


s


ソケットのディスクリプタ


*buf


受信したメッセージを入れるバッファ


len


バッファのサイズ


flags


recv()が呼び出されたときのプログラムの振舞を決める。


man を読んでも良く理解できない。0でデフォルトになる。



戻り値


成功時は、受信したメッセージのサイズ。失敗したときは-1





echoクライアント




#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#define RBUFFER 1024

void ExitError(char *message);

int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in echoServAddr;
unsigned short echoServPort;
char *ServIP;
char *echoString;
char echoBuffer[RBUFFER];
unsigned int echoStringLen;
int byteRec;
int byteTotal;


if(argc < 3){
fprintf(stderr,"Usage %s <ServIP> <Word>\n",argv[0]);
exit(1);
}

ServIP = argv[1];
echoString = argv[2];
echoServPort = 7;

printf("send =%s\n",echoString);


if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
ExitError("Error socket");

memset(&echoServAddr,0,sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = inet_addr(ServIP);
echoServAddr.sin_port = htons(echoServPort);


if(connect(sock,(struct sockaddr *) &echoServAddr,sizeof(echoServAddr)) < 0)
ExitError("Fail connect");

echoStringLen = strlen(echoString);


if(send(sock,echoString,echoStringLen,0) != echoStringLen)
ExitError("Fail send");

byteTotal = 0;
printf("Received=");

while(byteTotal != echoStringLen){
if((byteRec = recv(sock,echoBuffer,RBUFFER-1,0)) <= 0)

ExitError("recievesize error");

byteTotal += byteRec;
echoBuffer[byteRec] = '\0';
printf(echoBuffer);
}

printf("\n");

close(sock);

return 0;

}

void ExitError(char *message)
{
perror(message);
exit (1);
}





2007年8月28日火曜日

TCP/IPソケットプログラミングC言語編



ISBN:4274065197「TCP/IPソケットプログラミング」


知り合いに聞いたところ、薄くて読みやすい、必要な事は書いてあるとのことだったので、買ってみました。


たしかに薄めで、読みやすそうでした。


はてなダイアリーで検索してみても、よい評価をしている人が多かったので、間違ってなかったみたい。





2007年8月26日日曜日

PlamoLinuxでWLI-CB-AMG54HPを使う(ndiswrapper)



WLI-CB-AMG54HPっていう無線LANカードを中古で安く買ったんですが、カーネル標準のbcm43xxてドライバでは動かないようなので、ndiswrapperを使ってWinドライバで使うことにしました。





参考になるwebページ


1.かってにLinux20


2.LinuxでWindows用無線LANドライバを利用するには


3.中古ノート+Plamo Linux で無線LAN





事前にカーネルのソースをインストールしておく必要があります。





1.まず、buffaloのページからWin用のドライバをダウンロードします。


参考ページ1によると、8.52でもいけるそうですが、8.30でやっておきました。





2.次にndiswrapperのページからリンクをたどって、ダウンロードし、インストールします。



tar xzf ndiswrapper-1.47.tar.gz
cd ndiswrapper-1.47
make
su
make install

3.Win用のドライバを解凍します。



lha e wdrv_830.exe

4.ndiswrapperを使ってドライバをインストールします。



cd wdrv_830/CBG54/WIN2000
ndiswrapper -i netg54s.inf ドライバのインストール
ndiswrapper -l 確認
netg54s : driver installed
device (*****) present カードが刺さっていると表示される
ndiswrapper -m いろいろ設定してくれる




5./etc/ndiswrapper/netg54s/bwcdrv.sysを削除する。


良く分からないんですが、削除しとかないと動かないようです。





6.ndiswrapperをロードする。



modprobe ndiswrapper 上手くいけば、ここでカードのランプ点灯する。

自分の環境では、wlan0として認識しました。


はじめてだったので、/etc/network.mode、/etc/network.confなんかを設定しましあた


後は、iwconfig で設定して完了です。


/etc/network.mode



wlan0 -d

/etc/network.conf



wlan0,default,*)
INFO="wlan0 default"
DHCP=y
PPPOE=n
GATEWAY=+
DNS=+
;;

既存のものをコピーして、デバイスの名前の部分だけを変更しました。


wepキーなどを自動的に設定させるときには、/etc/wireless.confを設定してください。


設定方法は、参考ページの3が分かりやすいです。








速度測定してみてところ、6倍ぐらいの速度が出ていてびっくりしました。


買ってよかった!