TCP-echoサーバ Python socket module: Just a thin wrapper over the underlying C library's socket calls. TCP-echoサーバ TCP-echoサーバのプログラムモデル(Cプログラム) サーバのソケットオブジェクト ソケットオブジェクトの作成と削除(Cプログラム) サーバで利用するソケット関数(Cプログラム) TCP-echoサーバCプログラム(接続要求の窓口となるソケットを作成 ) TCP-echoサーバCプログラム(処理する要求に対して新しいソケットを作成 ) TCP-echoサーバCプログラム(クライアントからのメッセージ受信 と返信) TCP-echoサーバPythonプログラム TCP-echoサーバ ソケットによるデータ通信とTCP/IPネットワーク IPヘッダ情報 IP TCP TCPヘッダ情報 データ データ TCP/IP ネットワーク •通信プログラムを作成する上では、通信相手のソケットに自分の ソケットを繋ぐことができれば、安定した通信を行うことができる。 •安定した通信は、TCP/IPのプロトコルで自動的に対処される。 •ソケットを繋ぐことができれば、 マシン同士が、どの様な通信機器 や伝送経路を辿って、データを送受信しているかなどを気にする必 要は無くなる。 TCP-echoサーバ TCP-echoサーバのプログラムモデル (Cプログラム) TCPEchoClient TCPEchoServer 1. socket()を実行 (ソケット作成) socket() ↓ bind() 2. bind()を実行 listen() (ソケットにポート番号を割当る) socket() コネクション設定 3. listen()を実行 accept() connect() (接続要求をキューに入る) データ データ 4. accept()を実行 ”Hello” IP send() (接続要求毎に新ソケット作成) recv() TCP ↓ ”Hello” ”Hello” 5. send()とrecv()を実行 (データ通信を行う) ”Hello” recv() send() ↓ int recv(int socket, void *revBuffer, コネクション開放 unsigned int bufferLength, int flags) close() close() int send(int socket, const void *msg, unsigned int msgLength, int flags) ↓ 6. close()を実行 (ソケット削除) TCP-echoサーバ サーバのソケットオブジェクト 接続要求に対 するソケット サーバ クライアント1用ソケット データ クライアント2用ソケット listen() accept() accept() accept()待ちキュー TCP データ クライアント1 データ クライアント2 データ TCP-echoサーバ ソケットオブジェクトの作成と削除 (Cプログラム) PF_INET (TCP/IPの場合) ソケット作成 SOCK_STREAM (TCPの場合) SOCK_DGRAM (UDPの場合) int socket(int protocolFamily, int type, int protocol) 戻値: 成功:ソケット識別子、 失敗:-1 ソケット削除 IPPROTO_TCP (TCPの場合) IPPROTO_UDP (UDPの場合) 0 (デフォルト) ソケット識別子 int close(int socket) 接続要求に対 するソケット サーバ listen() accept() クライアント1用ソケット accept() クライアント1 クライアント2用ソケット accept()待ちキュー TCP データ データ クライアント2 データ データ TCP-echoサーバ サーバで利用するソケット関数 (Cプログラム) ソケットにポート番号を割当る int bind(int socket, struct sockaddr *localAddress, unsigned int addressLength) 戻値:成功: 0、失敗: -1 接続要求を同時に受入れる最大値 接続要求をキューに入る int listen(int socket, int queueLimit) 戻値:成功: 0、失敗: -1 接続要求毎に新しいソケットを作成 サーバのアドレス クライアントのアドレス int accept(int socket, struct sockaddr *clientAddress, unsigned int *addressLength) 戻値:成功: ソケット識別子、失敗: -1 接続要求に対 するソケット サーバ listen() accept() クライアント1用ソケット accept() クライアント1 クライアント2用ソケット accept()待ちキュー TCP データ データ クライアント2 データ データ TCP-echoサーバCプログラム (接続要求の窓口となるソケットを作成 ) TCP-echoサーバ TCPEchoServer.c HandleTCPClient.c DieWithError.c #define MAXPENDING 5 /* 最大キュー長 */ void DieWithError(char *errorMessage); /* エラー処理 */ void HandleTCPClient(int clntSocket); /* TCPクライアント処理 */ TCPEchoClient TCPEchoServer int main(int argc, char *argv[]) socket() { bind() int servSock; /* サーバのソケット識別子 */ listen() int clntSock; /* クライアントのソケット識別子 */ socket() struct sockaddr_in echoServAddr; /* ローカルアドレス */ コネクション設定 accept() struct sockaddr_in echoClntAddr; /* クライアントアドレス */ connect() unsigned short echoServPort; /* サーバポート */ データ unsigned int clntLen; /* クライアントアドレス構造体長 */ データ echoServPort = atoi(argv[1]); /* 引数1はローカルポート番号 */ ”Hello” IP send() recv() /*接続要求の窓口となるソケットを作成 */ TCP if ((servSock = socket(PF_INET, SOCK_STREAM, ”Hello” ”Hello” IPPROTO_TCP)) < 0) ”Hello” TCPソケットオブジェクト recv() DieWithError("socket() failed"); send() の生成 /* ローカルアドレス構造体を作る */ /*構造体を初期化*/ コネクション開放 memset(&echoServAddr, 0, sizeof(echoServAddr)); close() echoServAddr.sin_family = AF_INET; /* インターネットアドレス族 */ close() /*受信インタフェースを指定しないワイルドカード*/ echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* ローカルポート */ echoServAddr.sin_port = htons(echoServPort); TCP-echoサーバ TCP-echoサーバCプログラム (処理する要求に対して新しいソケットを作成 ) /* ローカルアドレスにバインドする */ if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr) < 0) DieWithError("bind() failed"); サーバの /* クライアントからの接続要求を待つ */ アドレス if (listen(servSock, MAXPENDING) < 0) DieWithError("listen() failed"); 接続要求を同 時に受入れる 最大値 TCPEchoClient TCPEchoServer socket() bind() listen() socket() connect() for (;;) /* 処理を永久に繰返す */ { データ /* 入出力パラメータのサイズをセットする */ send() clntLen = sizeof(echoClntAddr); /* 処理する要求に対して新しいソケットを作成 */ ”Hello” if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0) recv() DieWithError("accept() failed"); printf("Handling client %s\n", クライアント のアドレス inet_ntoa(echoClntAddr.sin_addr)); close() /* TCPクライアント処理関数を呼ぶ */ HandleTCPClient(clntSock); } 接続要求に対 } するソケット コネクション設定 accept() データ ”Hello” IP TCP recv() ”Hello” ”Hello” send() コネクション開放 close() TCP-echoサーバ TCP-echoサーバCプログラム (クライアントからのメッセージ受信 と返信) #define RCVBUFSIZE 32 /* Size of receive buffer */ void DieWithError(char *errorMessage); /* エラー処理 */ TCPEchoClient void HandleTCPClient(int clntSocket) { char echoBuffer[RCVBUFSIZE]; /* エコーバッファ */ int recvMsgSize; /* 受信メッセージ長 */ クライアント用 socket() ソケット識別子 /* クライアントからメッセージ受信 */ connect() if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) データ DieWithError("recv() failed"); while (recvMsgSize > 0) /* 0は転送終了を意味する */ send() { ”Hello” /* メッセージをクライアントに返す */ if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recv() recvMsgSize) DieWithError("send() failed"); /* 受信データがあるか確認する */ if ((recvMsgSize = recv(clntSocket, echoBuffer, close() RCVBUFSIZE, 0)) < 0) DieWithError("recv() failed"); } close(clntSocket); /* クライアントソケットを終了する */ } TCPEchoServer socket() bind() listen() コネクション設定 accept() データ ”Hello” IP TCP recv() ”Hello” ”Hello” send() コネクション開放 close() TCP-echoサーバ TCP-echoサーバPythonプログラム TCPEchoServer.py from socket import * my_host = "" my_port = 50007 def test(): sock_obj = socket(AF_INET, SOCK_STREAM) sock_obj.bind((my_host, my_port)) sock_obj.listen(5) # Infinte loop while 1: connection, address = sock_obj.accept() print "Server connected by", address while 1: data = connection.recv(1024) if data: print "Server received data : ", str(data) else: print "No data recevied" break connection.send("Echo>=" + data) connection.close() if __name__ == '__main__': print “TCPEchoServer", my_port test() TCPEchoClient TCPEchoServer socket() bind() listen() socket() connect() コネクション設定 データ accept() データ send() ”Hello” IP TCP ”Hello” recv() recv() ”Hello” ”Hello” send() コネクション開放 close() close()
© Copyright 2024 ExpyDoc