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

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

ただいまの
回答率

90.61%

  • C#

    6880questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Python 3.x

    5925questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • TCP

    160questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • UWP

    86questions

    UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

Python server, UWP(C#)client間でTCP通信がしたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 360

xsmiledur

score 2

 前提・実現したいこと

Pythonをサーバー,C#で書かれたUWPアプリケーションをクライアントとして,TCP通信で
Python→UWPにByte列(bytes)を送りたいです.
(画像の全画素値を送る目的で)

コードは
using Windows.Networking;
using Windows.Networking.Sockets;
Stream, StreamSocket, StreamWriter/ StreamReader
を使用して書いています.

C#→Pythonのbyte列送信はできています.
Python→C#ができないのです.

 該当のソースコード

using Windows.Networking;
using Windows.Networking.Sockets;
#endif

public class TcpNetworkClientManager
{
#if WINDOWS_UWP
    private StreamWriter writer = null;
    private StreamReader reader = null;
    private Stream st;
    private StreamSocket socket;

#endif
    private int len = 0;
    public byte[] read_output;
    public byte[] read_output_ASCII;
    public byte[] read_output_UTF8;
    public byte[] read_output_Unicode;
    public byte[] read_output_BigEudianUnicode;
    public string read_string;
    public string read_string_sjis;
    public string read_string2;
    public int read_int;
    public bool isReadable = false;
    public bool isStart = false;
    public Encoding encode;

    // データをReceiveしたかを確認する関数
    public bool CheckReadable()
    {
        if (isReadable == true)
        {
            isReadable = false;
            return true;
        }
        else return false;
    }


    // Start()関数内でnew TcpNetworkClientManager(...)として使う
    public TcpNetworkClientManager(string IP, int port)
    {
#if WINDOWS_UWP
        Debug.Log("Tcp Newtork Client Manager Start");
        Task.Run(async () =>
        {
            socket = new StreamSocket();
            await socket.ConnectAsync(new HostName(IP), port.ToString());

            st = socket.OutputStream.AsStreamForWrite();
            writer = new StreamWriter(st);
            Debug.Log("writer created");
            isStart = true;
        });
#endif
    }

    // 成功
    public void SendData(byte[] data)
    {
#if WINDOWS_UWP
        if (writer != null) Task.Run(async () =>
        {
            len = data.Length;
            writer.BaseStream.Write(data, 0, len);
            await writer.FlushAsync();
        });
#endif
    }

    // 失敗する
    public void RecieveData()
    {
#if WINDOWS_UWP
        List<byte> list_ = new List<byte>();
        read_output = new byte[len];


        Debug.Log("Receive Data Start");

        Task.Run(async () =>
        {

            // Read data from the echo server.
            string response;
            string received = "";
            char[] buf = new char[len];
            int x = -1;
            using (Stream inputStream = socket.InputStream.AsStreamForRead())
            {
                using (StreamReader streamReader = new StreamReader(inputStream))
                {
                    // encode = streamReader.CurrentEncoding;
                    // await streamReader.BaseStream.ReadAsync(read_output, 0, 1); // byte列を読み込む関数なのにうまくいかない.止まる.Readが終わらないみたい
                    // stringに代入する方法はあるが,byte列を実体の不明なstringに代入したところでうまくかない
                    response = await streamReader.ReadToEndAsync(); // 向こうが送ったのちにsocketを閉じたらいける.
                }
            }

            // 外から読み取れるpublic変数に代入
            read_int = x;
            read_string = response;

            // 以下,stringを色んなエンコードでbyte列に変えることをしているが,どれも中身が送り元の中身と違っている
            //read_output_ASCII = System.Text.Encoding.ASCII.GetBytes(read_string);
            //read_output_UTF8 = System.Text.Encoding.UTF8.GetBytes(read_string);
            //read_output_Unicode = System.Text.Encoding.Unicode.GetBytes(read_string);
            //read_output_BigEudianUnicode = System.Text.Encoding.BigEndianUnicode.GetBytes(read_string);
            isReadable = true;
        });
        Debug.Log("Receive Data End");
#else
        byte[] output = new byte[0];
        //return output;
#endif


    }
}
import socket
import time
from contextlib import closing
import fast_style_change as fsc
import numpy as np

def main():
    host = "192.168.0.4" #お使いのサーバーのホスト名を入れます
    port = 4000 #クライアントと同じPORTをしてあげます

    # 画像の行・列の大きさ
    dst_rows = 300
    dst_cols = 300

    serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serversock.bind((host,port)) #IPとPORTを指定してバインドします
    serversock.listen(10) #接続の待ち受けをします(キューの最大数を指定)

    print('Waiting for connections...')
    clientsock, client_address = serversock.accept() #接続されればデータを格納
    print("Succeeded in Connection!")

    while True:
        crop = clientsock.recv(3 * dst_rows * dst_cols)
        img = np.frombuffer(crop, np.uint8, -1) # ここで正しく読みとれているのは確認済み

        img_reshape = img.reshape(dst_rows, dst_cols, 3)
        output = fsc.stylize(img_reshape, 2, str(time.ctime()).replace(' ', '_').replace(':', '_') + "output.jpg", False) # ここも正しく処理できているのは確認済み

        # ここでC#に送るとC#側でうまく読みとれない
        clientsock.sendall(output.tobytes())
        # print(np.frombuffer(output.tobytes(), np.uint8, -1) # 正しく復元するので.tobyte()のバイト列変換も正しいとわかる
        break

    clientsock.close()

if __name__ == '__main__':
  main()

 試したこと

C#内で受け取るデータはstringとなるが,そのstringに対して色んなエンコーディングでbyte列に変換した.しかし,いずれも長さや中身の要素が送り元と異なっていた.

そもそもstringではなくbyte列で受け取る方がいいと思うのだが,そういう関数を使ったりすると計算が止まったりして進まなくなる.

StreamSocketではなく普通のSocket等でもいいのかもしれないが,
UWPで使えるSocket通信APIと検索してこれがヒットしたので使っているため,
SocketがUWPで使えるのかはそもそも不明です

教えていただけると幸いです.

 補足情報(FW/ツールのバージョンなど)

Python 3.6
Unity 2017.3.1f からビルドしたUWPアプリケーション
.NETは多分4.*とかです

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

Socketでゴリゴリ書きたがる人が多いですが。デバックが結構大変ですよ。。
WireSharkを導入して実際のパケットを確認してみることをお勧めします。

個人的には通信頻度の問題はありますが、HTTPまたはWebSocketでやり取りすることをお勧めしています。

C#側 HttpClientクラスを使用
Python側 http.serverもしくはWebフレームワークを使用。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

+1

結局BinaryRead(Stream)を使って解決しました.
DatagramSocketのUDP通信でそう書いてるコードを見かけて,同じ手筈でバイナリ受信ができました.
次回HTTP通信も試してみようと思います.ご回答ありがとうございました.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    6880questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Python 3.x

    5925questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • TCP

    160questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • UWP

    86questions

    UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。