0

私はPythonに比較的慣れていないので、思いやりを持ってください...

raw_sockets を介してサーバーとクライアントを実装しています。私は必要な権限を持っています。

今、私が定義したサーバー:

host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockSer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
sockSer.bind(address)
sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
packet, addr = sockSer .recvfrom(4096)   # wait for packet from client

Q1)なぜ単に入力できないのですか: hosts = 'localhost'. そうすると、sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) という行を書くことができなくなります。サーバーはクライアントのメッセージを受信しません。gethostbyname(socket.gethostname()) を実行する場合にのみ、192.168.1.101 を取得してから動作します。

別のクラス:クライアントソケット:

host = socket.gethostbyname(socket.gethostname())
address = (host, 22224)
sockCli = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)

Q2)次のように入力する必要がありますか? sockCli.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) または sockCli.connect(address)? connect コマンドがなくても動作するようです。クライアントソケットの?

今、私が次のことを行うと問題が発生します:1)クライアントからサーバーにパケットを送信します:

header=...
payload='a'
sockCli.sendto(header + payload, address)

2) サーバーでパケットを受信し、何かをクライアントに送り返します。

while(true):
    data, addr = sockSer.recvfrom(4096)
    header2=...
    payload2='b'
    sockSer.sendto(header2 + payload2, addr)

さて、私の重要な質問は次のとおりです 。Q3)サーバーはクライアントに 1 つのパケットのみを送信し、ペイロードは 'b' でした。何が起こるかというと、クライアントは実際に while ループで 2 つのパケットを受信します。最初のパケットはクライアント自体が serverに送信したもので、もう 1 つのパケットはクライアントがサーバーから取得したものです。したがって、私の出力は単に「b」ではなく「ab」です。なぜこれが起こっているのですか???

注: コード全体を入力したわけではありませんが、構文、解析、ヘッダー構成などは正しいと思います。私のコードに明らかな問題がありますか? 必要に応じて、コード全体をアップロードします。

ありがとう

4

2 に答える 2

0

私もこれを手に入れました。私の解決策は、受信コードにジャッジを追加することです。たとえば、Pingパッケージを送信して、ECHO Reply(タイプ0コード0)のみが必要な場合などです。

if type != 0:
     continue

addr == my_ip: continue のように書くこともできます

スムーズな解決策はないようです

于 2013-09-03T08:41:49.677 に答える
0

Q1: localhost にバインドし、両方のパラメーターを指定して IOCTL を呼び出すことができました。クライアントも同じシステムで実行されていると仮定すると、クライアントが「localhost」に送信していることを確認してください。そうしないと、サーバーはパケットを受信しません。クライアントが別のシステム上にある場合、明らかにサーバーはパケットを受信しません。

Q2: パケットの送信に IOCTL は必要ありません。sendto() 経由で送信するだけです。

Q3: 2 つの応答が表示されている理由は、カーネルが独自のユーザー空間コードに加えて、エコー リクエストも処理しているためです。

任意のメッセージ パッシングに ICMP を使用できますが、他の誰かが指摘したように、これは意図した設計ではありません。メッセージの返信でデータ部分が切り捨てられていることがあります。たとえば、echo リクエストを送信する場合、返信には送信したすべてが含まれる可能性があります。ただし、タイプ 3 コード 3 の応答には、データが含まれず、ICMP ヘッダーの最初の 8 バイトのみが含まれる場合があります。

于 2014-03-18T04:33:18.953 に答える