Transcript accept()

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-echoサーバのプログラムモデル
(Cプログラム)
1. socket()を実行 (ソケット作成)
↓
2. bind()を実行
(ソケットにポート番号を割当る)
3. listen()を実行
(接続要求をキューに入る)
4. accept()を実行
(接続要求毎に新ソケット作成)
↓
5. send()とrecv()を実行 (データ通信を行う)
↓
int recv(int socket, void *revBuffer,
unsigned int bufferLength, int flags)
int send(int socket, const void *msg,
unsigned int msgLength, int flags)
↓
6. close()を実行 (ソケット削除)
TCPEchoClient
socket()
connect()
send()
recv()
TCPEchoServer
socket()
bind()
listen()
コネクション設定
accept()
Echo this
Echo this
recv()
send()
コネクション開放
close()
close()
TCP-echoサーバ
サーバのソケットオブジェクト
サーバ
接続要求に対
するソケット
クライアント1用ソケット
クライアント2用ソケット
listen()
accept()
accept()
accept()待ちキュー
TCP
クライアント1
クライアント2
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)
サーバ
接続要求に対
するソケット
listen()
accept()
クライアント1用ソケット
accept()
accept()待ちキュー
TCP
クライアント1
クライアント2用ソケット
クライアント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()
accept()待ちキュー
TCP
クライアント1
クライアント2用ソケット
クライアント2
TCP-echoサーバ
TCP-echoサーバCプログラム
TCPEchoServer.c
HandleTCPClient.c
DieWithError.c
(接続要求の窓口となるソケットを作成 )
#define MAXPENDING 5 /* 最大キュー長 */
void DieWithError(char *errorMessage); /* エラー処理 */
void HandleTCPClient(int clntSocket); /* TCPクライアント処理 */
int main(int argc, char *argv[])
{
int servSock;
/* サーバのソケット識別子 */
int clntSock;
/* クライアントのソケット識別子 */
struct sockaddr_in echoServAddr; /* ローカルアドレス */
struct sockaddr_in echoClntAddr; /* クライアントアドレス */
unsigned short echoServPort; /* サーバポート */
unsigned int clntLen;
/* クライアントアドレス構造体長 */
echoServPort = atoi(argv[1]); /* 引数1はローカルポート番号 */
/*接続要求の窓口となるソケットを作成 */
if ((servSock = socket(PF_INET, SOCK_STREAM,
IPPROTO_TCP)) < 0)
TCPソケットオブジェクト
DieWithError("socket() failed");
の生成
/* ローカルアドレス構造体を作る */
/*構造体を初期化*/
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET; /* インターネットアドレス族 */
/*受信インタフェースを指定しないワイルドカード*/
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* ローカルポート */
echoServAddr.sin_port = htons(echoServPort);
TCPEchoClient
TCPEchoServer
socket()
bind()
listen()
socket()
connect()
send()
recv()
コネクション設定
Echo this
Echo this
accept()
recv()
send()
コネクション開放
close()
close()
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");
接続要求を同
時に受入れる
最大値
for (;;) /* 処理を永久に繰返す */
{
/* 入出力パラメータのサイズをセットする */
clntLen = sizeof(echoClntAddr);
/* 処理する要求に対して新しいソケットを作成 */
if ((clntSock = accept(servSock, (struct sockaddr *)
&echoClntAddr, &clntLen)) < 0)
DieWithError("accept() failed");
printf("Handling client %s\n",
クライアント
のアドレス
inet_ntoa(echoClntAddr.sin_addr));
TCPEchoClient
socket()
bind()
listen()
socket()
connect()
send()
recv()
}
}
接続要求に対
するソケット
コネクション設定
Echo this
Echo this
accept()
recv()
send()
コネクション開放
close()
/* TCPクライアント処理関数を呼ぶ */
HandleTCPClient(clntSock);
TCPEchoServer
close()
TCP-echoサーバ
TCP-echoサーバCプログラム
(クライアントからのメッセージ受信 と返信)
#define RCVBUFSIZE 32 /* Size of receive buffer */
void DieWithError(char *errorMessage); /* エラー処理 */
void HandleTCPClient(int clntSocket)
{
char echoBuffer[RCVBUFSIZE]; /* エコーバッファ */
int recvMsgSize; /* 受信メッセージ長 */
クライアント用
ソケット識別子
/* クライアントからメッセージ受信 */
if ((recvMsgSize = recv(clntSocket, echoBuffer,
RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
while (recvMsgSize > 0) /* 0は転送終了を意味する */
{
/* メッセージをクライアントに返す */
if (send(clntSocket, echoBuffer, recvMsgSize, 0) !=
recvMsgSize)
DieWithError("send() failed");
/* 受信データがあるか確認する */
if ((recvMsgSize = recv(clntSocket, echoBuffer,
RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
}
close(clntSocket); /* クライアントソケットを終了する */
}
TCPEchoClient
TCPEchoServer
socket()
bind()
listen()
socket()
connect()
send()
recv()
コネクション設定
Echo this
Echo this
accept()
recv()
send()
コネクション開放
close()
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()
send()
recv()
コネクション設定
Echo this
Echo this
accept()
recv()
send()
コネクション開放
close()
close()