首页 文章

在android socket中:在服务器中只接收到array []的一部分,socket中是否有最大大小?

提问于
浏览
0

我在android和服务器c#1-中开发了clint,当我发送小字符串作为“hello world”时它成功发送到服务器并且客户端也从服务器接收响应消息

2-现在,我试图从android发送LARGE字符串(实际上它是一个图像表示),字符串msg的大小是23.000字节 . THE PROBLEMS with the large string are:

1- the server c# did not receive  all the string bytes 
2- the response Msg did not received to the client

代码是 the same 在两个实验中ONly不同的字符串 size 请指教我

这是客户端android JAVA只有连接的功能:public void ConnectToServer(){

Thread ConnectToClient = new Thread(new Runnable() {

        @Override
        public void run() {try {
            Log.e("MESSAGE", "HERE void run");

            // time start here
            Log.e("MESSAGE", "Start time");
            long startTime = System.nanoTime();

            //Connect to socket 
            Log.e("MESSAGE", "HERE socket object");
            socket = new Socket(HOST, PORT);
              Log.e("MESSAGE", String.valueOf(client_str));
                        client_str = “hellow world”; //the problem if this string is huge i cannot write the string here it is too long


            DataOutputStream output_to_server = new DataOutputStream(socket.getOutputStream());
            output_to_server.writeBytes(client_str);
            output_to_server.flush();
               //receive ACK from (server)
                                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    Log.e("MESSAGE", "Recieve the ACK from server");
                    recievedMsg = in.readLine();

                    Log.e("MESSAGE", String.valueOf(recievedMsg));

            //Update TextView
            Message msg = null;
            msg = textview_handler_thread.obtainMessage();
            msg.obj = recievedMsg;
            textview_handler_thread.sendMessage(msg);

        } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    ConnectToClient.start();
}

这是c#服务器:

namespace CloudLet1Code
{
public static class Program
{
    public static void Main(string[] args)
    {
        IPAddress ipAdress = IPAddress.Parse("192.168.1.4");

            // Initializes the Listener
        TcpListener listener = new TcpListener(ipAdress, 4003);
        // Start Listeneting at the specified port
        listener.Start();

        Console.WriteLine("Server running - Port: 4003");
        Console.WriteLine("Local end point:" + listener.LocalEndpoint);
        Console.WriteLine("Waiting for connections...");

        Socket s = listener.AcceptSocket();
        // When accepted
        Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
        byte[] b = new byte[1000000];
        string rcvd_msg = null;        
        int k = s.Receive(b);
        Console.WriteLine("Recieved...\n");

         for (int i = 0; i < k; i++)
         {
              Console.Write(Convert.ToChar(b[i]));
             rcvd_msg += Convert.ToChar(b[i]).ToString();
         }
        Console.WriteLine("\nrcvd_msg = " + rcvd_msg);
        listener.Stop();
        Console.WriteLine("Automatic message sent!");

        ///send ack
        ASCIIEncoding asen = new ASCIIEncoding();
        s.Send(asen.GetBytes("The string was recieved by the server number 1."));
        Console.WriteLine("\nSent Acknowledgement");
        // ack sent 
        s.Close();

    }
}

更新的代码(c#)..以块的形式接收数据,但仍然无法提取字符串:

public static class Program
{
    public static void Main(string[] args)
    {
        IPAddress ipAdress = IPAddress.Parse("192.168.1.2");

        // Initializes the Listener
        TcpListener listener = new TcpListener(ipAdress, 4003);
        // Start Listeneting at the specified port
        listener.Start();

        Console.WriteLine("Server running - Port: 4003");
        Console.WriteLine("Local end point:" + listener.LocalEndpoint);
        Console.WriteLine("Waiting for connections...");

        Socket s = listener.AcceptSocket();
        // When accepted
        Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);


        MemoryStream bufferStream = new MemoryStream();
        byte[] buffer = new byte[1024];
        int count;
        //keep reading blocks from stream until there is no more data received
        //receive will block until there is data or the end of the stream has been reached
        while((count = s.Receive(buffer))!=0)
        {
            //write all received bytes into buffer stream ( which is in memory byte stream)
            bufferStream.Write(buffer, 0, count);
        }
        //get the entire brte array from the stream
        byte[] entireData = bufferStream.ToArray();
        //convert the received data to string using ascii incoding 
        String ReceivingDataString = System.Text.Encoding.ASCII.GetString(entireData);


        Console.WriteLine("Automatic message sent!");

        ///send ack

        ASCIIEncoding asen = new ASCIIEncoding();
        s.Send(asen.GetBytes("The string was recieved by the server number 1."));
        Console.WriteLine("\nSent Acknowledgement");
        // ack sent 
        s.Close();


    }

2 回答

  • 0

    我猜你的C#应用程序中的问题是在 int k = s.Receive(b); 行 . 这是因为这样一个大的数据块不一定会到达1个数据包,这意味着一次调用 Socket.Receive() 就不能获得整个流体 . 您可以尝试将其放入循环中,并继续读取所有数据,直到没有可用的数据(流的末尾) . 看看https://msdn.microsoft.com/en-us/library/8s4y8aff(v=vs.110).aspx,特别是底部的备注:

    “如果您使用的是面向连接的套接字,则Receive方法将读取尽可能多的数据”

    这就是说,如果有任何可用数据,它将立即返回 - 它不会等待流结束,然后返回所有可用数据并将其加载到缓冲区中(因为可能流是千兆字节长,可能不会适合记忆) . 以下示例显示了一个快速示例,说明如何开始实现以块的形式接收数据并将它们缓冲到MemoryStream中 .

    Socket s = yoursocket;
    MemoryStream bufferStream = new MemoryStream();
    byte[] buffer = new byte[1024];
    int count;
    // Keep reading blocks from the stream until there is no more data being received.
    // As specified in the docs, Receive will block until there is data - or the end of the
    // stream has been reached.
    while((count = s.Receive(buffer)) != 0)
    {
        // Write all received bytes into the buffer stream
        // (which is an in memory byte stream)
        bufferStream.Write(buffer, 0, count);
    }
    
    // Get the entire byte array from the stream
    byte[] entireData = bufferStream.ToArray();
    
    // Convert the received data to a string using ascii encoding
    string receivedDataAsString = System.Text.Encoding.ASCII.GetString(entireData);
    

    作为旁注,由于您发送的图像不应该使用文本编码(例如ASCII编码),但这与实际问题无关,阻止一次性接收所有数据 . 我希望这能让您深入了解如何解决问题 .

    编辑:Socket.Receive()将不会返回0,直到远程对等方结束流 . 不再发送数据不构成流的结束 . 因此,为了导致上面的示例循环( while((count = s.Receive(buffer)) != 0) 爆发,您的远程对等体需要完全关闭流 . (在您的情况下使用 DataOutputStream.close() ) . 此外,您需要捕获Socket抛出的一些异常 . 基于远程对等体将在其下显示断开连接的不同场景(例如,超时)接收 . 如果您想要在不等待流关闭的情况下处理数据,则需要在数据到达时使用 - 直接在内部在我的例子中循环 . 例如:

    while((count = s.Receive(buffer)) != 0)
        {
            // Convert the current buffer to a string (using the number of read bytes as the length of this string)
            string newText = System.Text.Encoding.ASCII.GetString(buffer, 0, count);
           //Console.WriteLine($"New data received: {newText}");
        }
    
  • -1

    我给你的最好建议(我非常有意识地提出这个作为“答案......”)是......

    ...... STOP! ......

    你在这里的“直接目标”(因此,“你的直接问题”)是:“通过套接字成功发送23KB . ”

    在这一点上,你“正在做一件已经完成过的事情,之前已有数千次 . ”事实上,你正在发明一个完整的协议 . 当然,这完全是不必要的,因为无论你现在在做什么,“它已经在以前完成了 . ” STOP 并寻找已经知道如何为你解决这个问题的现有技术 . (你将有很多自己需要解决的bug . 因此,随时可以在任何地方抢夺已经调试过的代码(!)你可以找到它 . )

    Actum Ne Agas:不做任何事情 . ™

相关问题