#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#define MAX 255
void exitWithError(char *message);
int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in echoServAddr;
struct sockaddr_in echoCliAddr;
unsigned int cliAddrLen;
char echoBuffer[MAX];
unsigned short echoServPort;
int recvMsgSize;
if(argc != 2){
fprintf(stderr,"Usage %s <Port>\n,argv[0]");
exit (1);
}
echoServPort = atoi(argv[1]);
if((sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
exitWithError("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(sock,(struct sockaddr *)&echoServAddr,sizeof(echoServAddr)) < 0)
exitWithError("bind() error\n");
for(;;)
{
cliAddrLen = sizeof(echoCliAddr);
if((recvMsgSize = recvfrom(sock,echoBuffer,MAX,0,(struct sockaddr *)&echoCliAddr,&cliAddrLen)) < 0)
exitWithError("recvfrom() error\n");
printf("Handling: %s\n",inet_ntoa(echoCliAddr.sin_addr));
if(sendto(sock,echoBuffer,recvMsgSize,0,(struct sockaddr *)&echoCliAddr,sizeof(echoCliAddr)) != recvMsgSize)
exitWithError("sendto() bytes error\n");
}
}
void exitWithError(char *message)
{
printf("%s\n",message);
exit(1);
}
2007年9月9日日曜日
UDP版echoサーバ
2007年9月7日金曜日
UDP版echoクライアント
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#define MAX 255
void exitWithError(char *message);
int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in servAddr;
struct sockaddr_in fromAddr;
unsigned short servPort;
unsigned int fromSize;
char *echoString;
char *servIP;
char echoBuffer[MAX+1];
int echoStringLen;
int recvStringLen;
if(argc < 3){
fprintf(stderr,"Usage: %s <ServIP> <Word> [<Serv Port>]\n",argv[0]);
exit (1);
}
echoString = argv[2];
servIP = argv[1];
if((echoStringLen = strlen(echoString)) > MAX)
exitWithError("word is too long\n");
if(argc == 4)
servPort = atoi(argv[3]);
else
servPort = 7;
if((sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
exitWithError("sockt() error\n");
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(servIP);
servAddr.sin_port = htons(servPort);
if(sendto(sock,echoString,echoStringLen,0,(struct sockaddr *) &servAddr,sizeof(servAddr)) != echoStringLen)
exitWithError("sendto() error\n");
fromSize = sizeof(fromAddr);
if((recvStringLen = recvfrom(sock,echoBuffer,MAX,0,(struct sockaddr *) &fromAddr,&fromSize)) != echoStringLen)
exitWithError("recvfrom() error\n");
if(servAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr)
{
fprintf(stderr,"recv from unkown host\n");
exit (1);
}
echoBuffer[recvStringLen] = '\0';
printf("Received: %s\n",echoBuffer);
close(sock);
return 0;
}
void exitWithError(char *message)
{
printf("%s\n",message);
exit (1);
}
コンパイルも通って実行もできるのに、なぜかエコーされてこないと思ったら
udpのエコーサーバが動いてませんでした。。。。
それで1時間ぐらい悩んでしまいました。
2007年9月4日火曜日
daytimeクライアント
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>
#define RCVSIZE 1024
void exitError(char *message);
int main(int argc,char *argv[])
{
int sock;
char buffer[RCVSIZE];
char *servIP;
struct sockaddr_in sockaddr;
int bytes=0;
if(argc < 1)
{
fprintf(stderr,"Usage %s <servIP>\n",argv[0]);
exit (1);
}
servIP = argv[1];
if((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
exitError("socket() error\n");
memset(&sockaddr,0,sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = inet_addr(servIP);
sockaddr.sin_port = htons(13);
if(connect(sock,(struct sockaddr *) &sockaddr,sizeof(sockaddr)) < 0)
exitError("connect error\n");
while(recv(sock,buffer,RCVSIZE,0) >= 1)
{
printf("%s",buffer);
}
close(sock);
}
void exitError(char *message)
{
printf("%s\n",message);
exit (1);
}
2007年9月3日月曜日
これまでのまとめ
クライアントの方は、
- 1.socket()でソケットを作成する。
- 2.connect()でサーバへ接続する。
- 3.send()で送信、recv()で受信する。
- 4.close()で接続を切断し、ソケットを破棄する。
サーバの方は、
- 1.socket()でソケットを作成する。
- 2.bind()でソケットにポート番号を割り当てる。
- 3.listen()でソケットを接続待ちにする。
- 4.accept()を呼び出してソケットを新しくつくる。
- 5.recv()で受信、send()で送信する。
- 6.close()で接続を切断、新しく作ったソケットを破棄する。
ソケット関連の関数のメモ3
CPUのバイトオーダの関係で送受信したバイトの順序がおかしくなるので、
送信する順序を統一する必要がある。そのために、送信前に変換する。
long int htonl(long int hostLong)
short int htons(short int hostShort)
ホストのバイトオーダからネットワークバイトオーダに変換する。
long int ntohl(long int netLong)
short int ntohs(short int netShort)
ホストのバイトオーダからネットワークバイトオーダに変換する。
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進数に変換する。
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);
}