Hello

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プログラム)
1. socket()を実行 (ソケット作成)
↓
2. connect()を実行 (サーバ接続)
↓
3. send()とrecv()を実行 (データ通信を行う)
↓
送信メッセージの
ソケット識別子
アドレス
int send(int socket, const void *msg,
unsigned int msgLength, int flags)
TCPEchoClient
TCPEchoServer
socket()
bind()
listen()
socket()
connect()
コネクション設定
データ
データ
send()
”Hello”
IP
TCP
”Hello”
戻値は送信バイト数
0はデフォルトの振舞
recv()
ソケット識別子
戻値は受信バイト数
0はデフォルトの振舞
↓
4. close()を実行 (ソケット削除)
recv()
”Hello”
”Hello”
送信バッファ
のアドレス
int recv(int socket, void *revBuffer,
unsigned int bufferLength, int flags)
accept()
send()
コネクション開放
close()
close()
TCP-echoクライアント
クライアントのソケットオブジェクト
データ
データ
AP
AP
データ
AP
AP
ソケット
ソケット
1 2
65535 1 2
IP
AP
AP
ソケット
ソケット
1 2
65535
TCP
UDP
データ
65535 1 2
TCP
UDP
IP
TCP
65535
IP
TCP-echoクライアント
ソケットオブジェクトの作成と削除
(Cプログラム)
SOCK_STREAM (TCPの場合)
SOCK_DGRAM (UDPの場合)
PF_INET (TCP/IPの場合)

ソケット作成



int socket(int protocolFamily, int type, int protocol)
戻値: 成功:ソケット識別子、 失敗:-1
IPPROTO_TCP (TCPの場合)
ソケット削除

IPPROTO_UDP (UDPの場合)
0 (デフォルト)
ソケット識別子
int close(int socket)
データ
データ
AP
AP
AP
ソケット
ソケット
IP 1
65535
TCP
1 2
2
65535
TCP
UDP
IP
TCP-echoクライアント
サーバのアドレスの指定と接続
(Cプログラム)

ソケット識別子
サーバ接続
サーバのIPアドレスとポート番号
int connect(int socket, struct sockaddr *foreinAddress, unsigned
int addressLength)
os、ネットワークの違いを吸収
sa_data
sa_family
ビットの並び(14バイト)
ファミリ
2バイト
sin_family
2バイト
sin_port
4バイト
sin_addr
8バイト
sin_zero
ファミリ ポート IPアドレス
AF_INET
(TCP/IPの場合)
ポート番号
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
未使用
IPアドレス
struct sockaddr_in {
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
TCP-echoクライアント
TCP-echoクライアントCプログラム
(サーバへ接続するソケットを作成 )
void DieWithError(char *errorMessage); /* エラー処理 */
TCPEchoClient.c
TCPEchoClient
int main(int argc, char *argv[])
{
int sock; // ソケット識別子
struct sockaddr_in echoServAddr; // エコーサーバのIPアドレス
socket()
char *servIP; //サーバのIPアドレス(10進表記)
char *echoString; //エコー文字列
connect()
unsigned short echoServPort; //エコーサーバのポート番号
データ
char echoBuffer[RCVBUFSIZE]; //エコー文字列受信時のバッファ
unsigned int echoStringLen; //エコー文字列の長さ
send()
int bytesRcvd, totalBytesRcvd; // 1回のrecv()で読むバイト数
と全バイト数
”Hello”
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");
recv()
DieWithError.c
TCPEchoServer
socket()
bind()
listen()
コネクション設定
accept()
データ
”Hello”
IP
TCP
recv()
”Hello”
”Hello”
send()
コネクション開放
close()
close()
TCP-echoクライアント
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);
TCPEchoClient
TCPEchoServer
socket()
bind()
listen()
socket()
connect()
コネクション設定
データ
サーバ接続
// エコーサーバに接続
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");
accept()
データ
send()
”Hello”
IP
TCP
”Hello”
recv()
recv()
”Hello”
”Hello”
send()
コネクション開放
close()
close()
TCP-echoクライアント
TCP-echoクライアントCプログラム
(サーバからの返信メッセージの受信 )
// エコー文字列をサーバから受信
TCPEchoClient TCPEchoServer
totalBytesRcvd = 0;
受信
printf("Received: ");
socket()
// バッファサイズまで、エコー文字列を受信
bind()
while (totalBytesRcvd < echoStringLen)
listen()
{
socket()
if ((bytesRcvd = recv(sock, echoBuffer,
コネクション設定
accept()
RCVBUFSIZE - 1, 0)) <= 0)
connect()
DieWithError("recv() failed or connection closed
データ
データ
prematurely");
// 総受信バイト数を求める
”Hello”
IP
send()
recv()
totalBytesRcvd += bytesRcvd;
TCP
// 文字列の終了(NULL)を追加
”Hello”
”Hello”
echoBuffer[bytesRcvd] = '\0';
”Hello”
recv()
// エコーバッファの内容を表示
send()
printf(echoBuffer);
}
コネクション開放
// ラインフィード
close()
close()
printf("\n");
ソケット削除
// ソケットのクローズ
close(sock);
exit(0);
}
TCP-echoクライアント
TCP-echoクライアントPythonプログラム
import sys
from socket import *
TCPEchoClient.py
TCPEchoClient
TCPEchoServer
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()
socket()
bind()
listen()
socket()
connect()
コネクション設定
データ
accept()
データ
send()
”Hello”
IP
TCP
”Hello”
recv()
recv()
”Hello”
”Hello”
send()
コネクション開放
close()
close()