我在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 回答
我猜你的C#应用程序中的问题是在
int k = s.Receive(b);
行 . 这是因为这样一个大的数据块不一定会到达1个数据包,这意味着一次调用Socket.Receive()
就不能获得整个流体 . 您可以尝试将其放入循环中,并继续读取所有数据,直到没有可用的数据(流的末尾) . 看看https://msdn.microsoft.com/en-us/library/8s4y8aff(v=vs.110).aspx,特别是底部的备注:这就是说,如果有任何可用数据,它将立即返回 - 它不会等待流结束,然后返回所有可用数据并将其加载到缓冲区中(因为可能流是千兆字节长,可能不会适合记忆) . 以下示例显示了一个快速示例,说明如何开始实现以块的形式接收数据并将它们缓冲到MemoryStream中 .
作为旁注,由于您发送的图像不应该使用文本编码(例如ASCII编码),但这与实际问题无关,阻止一次性接收所有数据 . 我希望这能让您深入了解如何解决问题 .
编辑:Socket.Receive()将不会返回0,直到远程对等方结束流 . 不再发送数据不构成流的结束 . 因此,为了导致上面的示例循环(
while((count = s.Receive(buffer)) != 0)
爆发,您的远程对等体需要完全关闭流 . (在您的情况下使用DataOutputStream.close()
) . 此外,您需要捕获Socket抛出的一些异常 . 基于远程对等体将在其下显示断开连接的不同场景(例如,超时)接收 . 如果您想要在不等待流关闭的情况下处理数据,则需要在数据到达时使用 - 直接在内部在我的例子中循环 . 例如:我给你的最好建议(我非常有意识地提出这个作为“答案......”)是......
...... STOP! ......
你在这里的“直接目标”(因此,“你的直接问题”)是:“通过套接字成功发送23KB . ”
在这一点上,你“正在做一件已经完成过的事情,之前已有数千次 . ”事实上,你正在发明一个完整的协议 . 当然,这完全是不必要的,因为无论你现在在做什么,“它已经在以前完成了 . ” STOP 并寻找已经知道如何为你解决这个问题的现有技术 . (你将有很多自己需要解决的bug . 因此,随时可以在任何地方抢夺已经调试过的代码(!)你可以找到它 . )