3

MSDN でここに示されているように、Windows Phone で単純な TCP クライアントを開発しました。

これは期待どおりに機能しています。

ここで、このクライアントを介して非常に大きなBase64文字列を送信したいと考えています (画像を転送するため)。しかし、このクライアントからBase64文字列を送信しようとすると、サーバーで文字列の一部しか受信できないため、サーバーで画像全体を生成できません。

文字列を受信するためのサーバー側のコードは次のとおりです: (編集済み)

            IPAddress ipAd = IPAddress.Any;

            Console.Write("Port No. (leave blank for port 8001): ");
            string port;
            port = Console.ReadLine();

            if (port == "")
                port = "8001";

            /* Initializes the Listener */
            TcpListener myList = new TcpListener(ipAd, int.Parse(port));

            /* Start Listeneting at the specified port */
            myList.Start();                

            Console.WriteLine("\nThe server is running at port " + port);
            Console.WriteLine("The local End point is  :" +
                              myList.LocalEndpoint);
            Console.WriteLine("\nWaiting for a connection.....");

            Socket s = myList.AcceptSocket();
            Console.WriteLine("\nConnection accepted from " + s.RemoteEndPoint);

            byte[] b = new byte[5 * 1024 * 1024]; // BIG SIZE for byte array, is this correct?
            String message = String.Empty;

            int k = s.Receive(b);
            Console.WriteLine("\nRecieved...");
            for (int i = 0; i < k; i++)
            {
                message += Convert.ToChar(b[i]);
                Console.Write(Convert.ToChar(b[i]));
            }

            System.IO.File.WriteAllText(@"Message.txt", message);  // write it to a file

            ASCIIEncoding asen = new ASCIIEncoding();
            s.Send(asen.GetBytes("The string was recieved by the server."));
            Console.WriteLine("\n\nSent Acknowledgement");
            /* clean up */
            s.Close();
            myList.Stop();

私は本当にここで立ち往生しています。私を助けてください。

問題はサーバーではなくクライアントにあると思います。助けてください。

クライアントで使用したクラスは、上記のMSDN の記事で見つけることができます。

PS: クラスのTIMEOUT_MILLISECONDSMAX_BUFFER_SIZEの値を増やしてみました。しかし、それは役に立ちませんでした。

アップデート:

クライアント側のコードは次のとおりです (参照については、MSDN のこちらを参照してください)。

        // Make sure we can perform this action with valid data
        if (ValidateRemoteHost() && ValidateInput())
        {
            // Instantiate the SocketClient
            SocketClient client = new SocketClient();

            // Attempt to connect to the echo server
            Log(String.Format("Connecting to server '{0}' over port {1} (echo) ...", txtRemoteHost.Text, ECHO_PORT), true);
            string result = client.Connect(txtRemoteHost.Text, ECHO_PORT);
            Log(result, false);

            byte[] bytearray = null;

            // Attempt to send our message to be echoed to the echo server
            Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true);
            if (checkBox1.IsChecked == true)  // this checkbox is for image selection
            {


                // This is the part where we send images


                using (MemoryStream ms = new MemoryStream())
                {
                    WriteableBitmap wbitmp = new WriteableBitmap((BitmapImage)image1.Source);

                    wbitmp.SaveJpeg(ms, (int)wbitmp.PixelWidth, (int)wbitmp.PixelHeight, 0, 10);
                    bytearray = ms.ToArray();
                    string str = Convert.ToBase64String(bytearray);                        

                    result = client.Send(str);
                    System.Diagnostics.Debug.WriteLine("\n\nMessge sent:\n\n" + str + "\n\n");
                }                                        
            }
            else
            {
                result = client.Send(txtInput.Text);
            }

            Log(result, false);

            // Receive a response from the server
            Log("Requesting Receive ...", true);
            result = client.Receive();
            Log(result, false);

            // Close the socket connection explicitly
            client.Close();
        }
4

1 に答える 1

-2
                    while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0)
                    {
                        Fs.Write(RecData, 0, RecBytes);
                        totalrecbytes += RecBytes;
                    }

編集:コードのそのセクションが削減されました

        int k = s.Receive(b);

悪いことです。すべてのデータが一度に完全に送信されることを前提としていますが、これはネットワークの仕組みではありません。

2 つのオプション:

  • 文字列の先頭に、必要な長さを含めます。
  • 文字列の最後に、メッセージの他の場所にはない終了記号 (おそらく null) を付けます。

次に、その while ループは、全長が見つかるか終了シンボルが見つかるまで続行する必要があります。

(また、Base64 を送信することは、回避できる場合にはお勧めできません。生のバイトのストリームとして送信してみませんか?)

[ED: この部分はもはや関係ありません](また、サーバーがファイルの保存場所を選択するのはなぜですか [そして、サーバーが選択するまですべてを遅らせます] - クライアントは最初にファイルを保存する場所を示し、次にサーバーは単に健全性をチェックします.[非常に正当な理由がない限り、そのようにしないでください])

編集:私が言っていたことの簡単な実装:

このサーバーコード

        int k = s.Receive(b);
        Console.WriteLine("\nRecieved...");
        for (int i = 0; i < k; i++)
        {
            message += Convert.ToChar(b[i]);
            Console.Write(Convert.ToChar(b[i]));
        }

への変更

        while (true)
        {
            int k = s.Receive(b);
            Console.WriteLine("\nRecieved...");
            for (int i = 0; i < k; i++)
            {
                char bc = Convert.ToChar(b[i]); // This is a very wrong way of doing this but it works I guess meh.
                if (bc == ' ')
                { // You've struck the end! Get out of this infinite loop!
                    goto endmyloop;
                }
                message += bc;
                Console.Write(bc);
            }
        }
        endmyloop:

このクライアント コードの一部

                result = client.Send(str);

への変更

                result = client.Send(str + " ");

-- Base64 ではスペースを含めることができないため、末尾を示すために使用されます。

クライアントがエラーを起こした場合 (そして何らかの奇妙な理由で最後にスペースを送信しない場合)、このコードは永久に while ループに閉じ込められることに注意してください (ゼロ CPU 使用率の無限待機)。

于 2013-07-01T06:35:29.200 に答える