質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

9104閲覧

pythonによるソケット通信でデータを少しずつ受信する方法について

hawk_daily

総合スコア9

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/08/27 07:13

編集2020/08/27 08:01

<背景>
pythonでソケット通信の勉強をしています。
recv()のバッファサイズについて、よく参考書では1024バイトなどが固定で指定されていますが、仮にバッファよりも大きいデータが来た場合,対応するにはどうしたらよいかという疑問に行きつきました。
そこで、recv()をループさせて、とりあえず1バイトずつ読み取って、最後に合算したデータをクライアントに送信できないかと思い、以下のプログラムを書いてみました。

<ご質問内容>
recv()をwhileでループして、データを「data_total」変数に足し合わせていき、最後までデータを読んだところで、まとめてクライアントに送りたいのですが、以下のプログラムではrecvで最後まで読んだ後に、「if not data:」の条件文までいかずに、recv()で止まってしまいます。
どのようにしたらrecv()で止まらずに「if not data:」の条件文でブレイクできるでしょうか。
ご教示の程何卒よろしくお願い致します。

python

1#server側 2import socket 3 4def server(): 5 with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s: 6 s.bind(("127.0.0.1",8888)) 7 s.listen(1) 8 conn,addr = s.accept() 9 with conn: 10 data_total = "".encode() 11 while True: 12 data = conn.recv(1) 13 print("data:{}".format(data)) 14 data_total += data 15 if not data: 16 conn.sendall(data_total) 17 break 18 19if __name__ == '__main__': 20 server()

python

1# client側 2import socket 3 4with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 5 s.connect(('127.0.0.1', 8888)) 6 s.sendall(b'test_message') 7 data = s.recv(1024) 8 print(repr(data))

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/08/27 07:53

うまくいかないとはどううまくいかないんでしょうか
hawk_daily

2020/08/27 08:04

抽象的で大変申し訳ございません。recv()をループさせて、読み込むデータがなくなったらブレイクしたいのですが、データをすべて読み込み、最後に空のデータを読み込むrecv()でブロックされて止まってしまいます。一応デバッグモードで確認してみました。
y_waiwai

2020/08/27 08:06

そりゃデータが来るのを待ってるんじゃないんでしょうか。 空のデータを読むって意味不明ですよ
hawk_daily

2020/08/27 08:20

申し訳ございません。 if not data:という条件文でよくループを抜けているソースをよく見かけるのですが、これは、recv()で受けたデータが空かどうかの判定をしているのではと思ったので、「空のデータを読む」と表現しました。。
otn

2020/08/27 09:47 編集

空なら何がデータが来るまで待ちます。 待ちたくない場合はノンブロッキングモードにします。 おかしな事を考えずに普通に書けば良いと思いますよ。
hawk_daily

2020/08/27 09:59

ありがとうございます。 if not data:という条件文はノンブロッキングモードでしか意味をなさないという事でしょうか。 以下リンクのプログラムではノンブロッキングモードでソケットを使用していないように思いますが、いかがでしょうか。質問ばかりで申し訳ございません。 https://qiita.com/__init__/items/5c89fa5b37b8c5ed32a4
bsdfan

2020/08/27 14:37

if not data は、相手がソケットをクローズしたかをチェックします。
hawk_daily

2020/08/27 21:38

if not dataは相手のソケッドをチェックしているのですか!なるほど、それであれば私もしっくりきます。 それにしても、ここで質問するにあたって「PythonによるTCP/IPソケットプログラミング」という本を読みましたが、if not dataは「受信するものがないならブレイク」と書いてありましたので、勘違いしてしまいました。ご回答ありがとうございます。
guest

回答2

0

ベストアンサー

recv は、ブロッキングモードで動作します。ブロッキング動作では、データが来ていなければ来るまで待ち、データがあれば、そのときに得られるデータを指定したサイズ分取得して返します。、

質問の回答で提示されているリンク先の例もブロッキングですから、1024バイト以上のデータをやりとりすることはできません。

ノンブロッキングであれば、recvはデータが来ていなくても返りますが、データが終りまで送られたのか、まだ来ていないのかの判定をするなどしなければなりません。そのあたりは、送信側との兼ね合い(プロトコル)によるので、それに合せて実装することになります。
このあたり にそういったときのヒントが書いてありますので、読んでみるといいと思います。

投稿2020/08/27 11:04

TakaiY

総合スコア12765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hawk_daily

2020/08/27 13:20

ご回答いただきありがとうございます。 recvの動作が理解できました。またリンク先のドキュメントも確認したいともいます。 追加でご教示いただきたいのですが、基本的にrecvは予めどのくらいのデータ量が来ることが解っている場合に使用することが多いという認識でよろしいのでしょうか。また、動的にrecvのバッファサイズを変更する方法や、ループなので繰り返しデータを読む方法などについてご存知であれば、ご教示いただきたく存じます。手数おかけして大変申し訳ございませんが、何卒よろしくお願いいたします。
hawk_daily

2020/08/27 21:27

五月雨式に失礼します。 その後、ご教示いただきましたリンク先を元にrecvを繰り返してデータを処理する方法がわかりました。 そのため上記の疑問は解決いたしました。 みなさまより様々なご指摘いただきましたが、こちらのご回答が最も私が知りたかった情報でしたので、ベストアンサーにさせていただきます。 みなさま誠にありがとうございました。
guest

0

data = conn.recv(1)

data_total += data

バイトデータを積算させてるようですが、何をしたいんでしょうか。

投稿2020/08/27 08:04

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hawk_daily

2020/08/27 08:24

1バイトずつループで読み込み、合算させたのちにクライアントにまとめ送信したいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問