UDPエコーサーバ UDP-echoサーバのプログラムモデル(Cプログラム) サーバで利用するソケット関数(Cプログラム) Python socket module: Just a thin wrapper over the underlying C library's socket calls. UDP-echoサーバのプログラムモデル(Cプログラム) サーバで利用するソケット関数(Cプログラム) UDP-echoサーバCプログラム(ソケットによる単純接続のリンクを作成 ) UDP-echoサーバCプログラム(クライアントからのメッセージの受信と返信) UDP-echoサーバPythonプログラム
UDP-echoサーバのプログラムモデル (Cプログラム) 1. socket()を実行 (ソケット作成) ↓ 2. bind() (ソケットにポート番号を割当る) 3. recvfrom()とsendto()を実行(データ通信を行う) int recvfrom(int socket, const void *msg, unsigned int msgLength, int flags, struct sockaddr *srcAddr, unsigned int *addrLen) int sendto(int socket, const void *msg, unsigned int msgLength, int flags, struct sockaddr *destAddr, unsigned int addrLen) 4. close()を実行 (ソケット削除) UDPEchoClient UDPEchoServer ソケットリンク接続 socket() bind() socket() Echo sendto() recvfrom() Echo recvfrom() sendto() ソケットリンク開放 close() close()
サーバで利用するソケット関数 (Cプログラム) サーバのアドレス ソケットにポート番号を割当る int bind(int socket, struct sockaddr *localAddress, unsigned int addressLength) 戻値:成功: 0、失敗: -1 sendto() サーバ プログラム UDP recvfrom() サーバのソケット クライアント1 クライアント2 ソケットにポート番号を割当る bind
UDP-echoサーバCプログラム (ソケットによる単純接続のリンクを作成 ) UDPEchoServer.c DieWithError.c #define ECHOMAX 255 /*エコー文字列の最大長 */ int main(int argc, char *argv[]) { int sock; /*ソケット識別子 */ struct sockaddr_in echoServAddr; /* ローカルアドレス */ struct sockaddr_in echoClntAddr; /* クライアントアドレス */ unsigned int cliAddrLen; /* 着信メッセージ長 */ char echoBuffer[ECHOMAX]; /* エコー文字列用バッファ */ unsigned short echoServPort; /* サーバのポート番号 */ int recvMsgSize; /* 受信メッセージ長 */ echoServPort = atoi(argv[1]); /* 1つ目の引数: ローカルアドレス */ /* データグラムの送受信に使うソケットを作成 */ if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) DieWithError("socket() failed"); /* ローカルのアドレス構造体を作成 */ memset(&echoServAddr, 0, sizeof(echoServAddr)); /* 0を埋める */ 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) DieWithError("bind() failed"); UDPEchoClient UDPEchoServer ソケットリンク接続 socket() bind() socket() Echo sendto() recvfrom() Echo recvfrom() sendto() ソケットリンク開放 close() close() bindでソケットにローカルアドレスを設定後、直に受信出来る(listen()不要)
UDP-echoサーバCプログラム (クライアントからのメッセージの受信と返信) UDPEchoClient UDPEchoServer クライアント毎にaccept()を実行して、ソケットを作る必要がない for (;;) /* 繰返し実行 */ { /* 入出力パラメータのサイズをセット */ cliAddrLen = sizeof(echoClntAddr); /* クライアントからのメッセージ待ち */ if ((recvMsgSize = recvfrom(sock, echoBuffer, ECHOMAX, 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)) < 0) DieWithError("recvfrom() failed"); printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr)); /* 受信したデータグラムをクライアントに返信 */ if (sendto(sock, echoBuffer, recvMsgSize, 0,(struct sockaddr *) &echoClntAddr, sizeof(echoClntAddr)) != recvMsgSize) DieWithError("sendto() sent a different number of bytes than expected"); } /* ここには到達しない */ ソケットリンク接続 socket() bind() socket() Echo sendto() recvfrom() Echo recvfrom() sendto() 1ソケットから複数のIPアドレスへ送信 ソケットリンク開放 close() close()
UDP-echoサーバPythonプログラム UDPEchoServer.py from socket import * my_host = "" recv_port = 50007 send_port = recv_port +1 def test(): sock_obj = socket(AF_INET, SOCK_DGRAM, 0) sock_obj.bind((my_host, recv_port)) # Infinte loop while 1: data, address = sock_obj.recvfrom(1024) if data: print "Server received data : ", str(data) else: print "No data recevied" break sock_obj.sendto("Echo>=" + str(data), (address[0], send_port)) sock_obj.close() if __name__ == '__main__': print "UDPEchoServer", recv_port, send_port test() UDPEchoClient UDPEchoServer Echo socket() sendto() recvfrom() close() bind() ソケットリンク接続 ソケットリンク開放