Transcript accept()
サーバプログラムとソケットオブジェクト
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プログラム
TCPエコーサーバの実際のスループット
サーバプログラムとソケットオブジェクト
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()
サーバプログラムとソケットオブジェクト
サーバのソケットオブジェクト
サーバ
接続要求に対
するソケット
クライアント1用ソケット
クライアント2用ソケット
listen()
accept()
accept()
accept()待ちキュー
TCP
クライアント1
クライアント2
サーバプログラムとソケットオブジェクト
ソケットオブジェクトの作成と削除
(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
サーバプログラムとソケットオブジェクト
サーバで利用するソケット関数
(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サーバ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サーバ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サーバ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サーバ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()
サーバプログラムとソケットオブジェクト
TCPエコーサーバの実際のスループット
サーバ
サービス
処理
listen()
一時に唯一のサービス
逐次的な処理
accept()
TCP
複数のクライアントから
同時にアクセスを受ける
クライアント クライアント クライアント クライアント クライアント