90 likes | 250 Views
TCP-echo クライアント. Python socket module: Just a thin wrapper over the underlying C library's socket calls. TCP-echo クライアントのプログラムモデル( C プログラム) クライアントのソケットオブジェクト ソケットオブジェクトの作成と削除( C プログラム) サーバへの接続とアドレスの指定( C プログラム) TCP -echo クライアント C プログラム(サーバへ 接続するソケットを作成 )
E N D
TCP-echoクライアント Python socket module: Just a thin wrapper over the underlying C library's socket calls. • TCP-echoクライアントのプログラムモデル(Cプログラム) • クライアントのソケットオブジェクト • ソケットオブジェクトの作成と削除(Cプログラム) • サーバへの接続とアドレスの指定(Cプログラム) • TCP-echoクライアントCプログラム(サーバへ接続するソケットを作成) • TCP-echoクライアントCプログラム(サーバへの接続、メッセージ送信) • TCP-echoクライアントCプログラム(サーバからの返信メッセージの受信) • TCP-echoクライアントPythonプログラム
1. socket()を実行 (ソケット作成) ↓ 2. connect()を実行 (サーバ接続) ↓ 3. send()とrecv()を実行 (データ通信を行う) ↓ int send(int socket, const void *msg, unsigned int msgLength, int flags) int recv(int socket, void *revBuffer, unsigned int bufferLength, int flags) ↓ 4. close()を実行 (ソケット削除) TCP-echoクライアントのプログラムモデル(Cプログラム) TCPEchoServer TCPEchoClient socket() bind() listen() accept() socket() コネクション設定 送信メッセージのアドレス connect() ソケット識別子 Echo this send() recv() 0はデフォルトの振舞 戻値は送信バイト数 Echo this recv() send() 送信バッファ のアドレス ソケット識別子 コネクション開放 close() close() 戻値は受信バイト数 0はデフォルトの振舞
AP AP AP AP AP AP ソケット ソケット ソケット ソケット 1 1 2 2 65535 65535 1 1 2 2 65535 65535 UDP UDP TCP TCP IP IP クライアントのソケットオブジェクト
AP AP AP ソケット ソケット 1 2 65535 1 2 65535 UDP TCP IP ソケットオブジェクトの作成と削除(Cプログラム) SOCK_STREAM (TCPの場合) SOCK_DGRAM (UDPの場合) PF_INET (TCP/IPの場合) • ソケット作成 • int socket(int protocolFamily, int type, int protocol) • 戻値: 成功:ソケット識別子、 失敗:-1 • ソケット削除 • int close(int socket) IPPROTO_TCP (TCPの場合)IPPROTO_UDP (UDPの場合) 0 (デフォルト) ソケット識別子
サーバ接続 int connect(int socket, struct sockaddr *foreinAddress, unsigned int addressLength) サーバのアドレスの指定と接続(Cプログラム) ソケット識別子 サーバのIPアドレスとポート番号 os、ネットワークの違いを吸収 sa_data sa_family • struct sockaddr { • unsigned short sa_family; • char sa_data[14]; • }; ファミリ ビットの並び(14バイト) 2バイト 2バイト 4バイト 8バイト sin_family sin_port sin_addr sin_zero • struct sockaddr_in { • unsigned short sin_family; • unsigned short sin_port; • struct in_addr sin_addr; • char sin_zero[8]; • }; ファミリ ポート IPアドレス 未使用 AF_INET (TCP/IPの場合) ポート番号 IPアドレス
TCP-echoクライアントCプログラム(サーバへ接続するソケットを作成)TCP-echoクライアントCプログラム(サーバへ接続するソケットを作成) TCPEchoClient.c DieWithError.c void DieWithError(char *errorMessage); /* エラー処理 */ int main(int argc, char *argv[]) { int sock; // ソケット識別子 struct sockaddr_in echoServAddr; // エコーサーバのIPアドレス char *servIP; //サーバのIPアドレス(10進表記) char *echoString; //エコー文字列 unsigned short echoServPort; //エコーサーバのポート番号 char echoBuffer[RCVBUFSIZE]; //エコー文字列受信時のバッファ unsigned int echoStringLen; //エコー文字列の長さ int bytesRcvd, totalBytesRcvd; // 1回のrecv()で読むバイト数と全バイト数 servIP = argv[1]; // 引数1は、サーバのIPアドレス echoString = argv[2]; //引数2は、エコー文字列 echoServPort = atoi(argv[3]); /* 引数3はローカルポート番号 */ // ストリームソケットを使う if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) DieWithError("socket() failed"); TCPEchoServer TCPEchoClient socket() bind() listen() accept() socket() コネクション設定 connect() Echo this send() recv() Echo this recv() send() コネクション開放 ソケット作成 close() close()
TCP-echoクライアントCプログラム(サーバへの接続、メッセージ送信)TCP-echoクライアントCプログラム(サーバへの接続、メッセージ送信) // サーバアドレス構造体を作成 // 構造体に0を埋める memset(&echoServAddr, 0, sizeof(echoServAddr)); // インタネットアドレスファミリ echoServAddr.sin_family = AF_INET; // サーバのIPアドレス echoServAddr.sin_addr.s_addr = inet_addr(servIP); // サーバのポート番号 echoServAddr.sin_port = htons(echoServPort); // エコーサーバに接続 if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))< 0) DieWithError("connect() failed"); // エコー文字列の長さを求める echoStringLen = strlen(echoString); // エコー文字列tを送信 if (send(sock, echoString, echoStringLen, 0) != echoStringLen) DieWithError("send() sent a different number of bytes than expected"); TCPEchoServer TCPEchoClient socket() bind() listen() accept() socket() コネクション設定 connect() サーバ接続 Echo this send() recv() Echo this recv() send() 送信 コネクション開放 close() close()
TCP-echoクライアントCプログラム(サーバからの返信メッセージの受信)TCP-echoクライアントCプログラム(サーバからの返信メッセージの受信) // エコー文字列をサーバから受信 totalBytesRcvd = 0; printf("Received: "); // バッファサイズまで、エコー文字列を受信 while (totalBytesRcvd < echoStringLen) { if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0) DieWithError("recv() failed or connection closed prematurely"); // 総受信バイト数を求める totalBytesRcvd += bytesRcvd; // 文字列の終了(NULL)を追加 echoBuffer[bytesRcvd] = '\0'; // エコーバッファの内容を表示 printf(echoBuffer); } // ラインフィード printf("\n"); // ソケットのクローズ close(sock); exit(0); } 受信 TCPEchoServer TCPEchoClient socket() bind() listen() accept() socket() コネクション設定 connect() Echo this send() recv() Echo this recv() send() コネクション開放 close() close() ソケット削除
TCP-echoクライアントPythonプログラム TCPEchoClient.py import sys from socket import * server_host = "localhost" server_port = 50007 def test(): global server_host message = ["Hello network world"] if len(sys.argv) > 1: server_host = sys.argv[1] if len(sys.argv) > 2: message = sys.argv[2:] sock_obj = socket(AF_INET, SOCK_STREAM) sock_obj.connect((server_host, server_port)) for line in message: sock_obj.send(line) data = sock_obj.recv(1024) print "Client received data : ", str(data) sock_obj.close() if __name__ == '__main__': print "TCPEchoClient", server_host, server_port test() TCPEchoServer TCPEchoClient socket() bind() listen() accept() socket() コネクション設定 connect() Echo this send() recv() Echo this recv() send() コネクション開放 close() close()