我和我的合作伙伴正在从事一个项目,我的合作伙伴正在Pascal中开发,并使用Indy10套接字进行网络连接,我正在C#下开发一个UWP项目。因此,对于网络,我必须使用streamsocket命名空间。
问题是,我的合作伙伴使用带有-1和假参数的ReadStream方法,这意味着接收流的长度不确定。因此,我必须从流中的数据(例如,使用BitConverter.GetBytes类)发送一个长度前缀(在本例中我使用的是DataWriter方法),继续使用数据本身。但是Indy10套接字没有收到任何信息。它看起来像是在等待包裹,或者我不知道。
有人碰到这个问题了吗?请帮帮忙,我们已经处理了大约两周了。我在StackOverflow上读过所有类似的问题,这是一个关于使用框架和分隔的博客。在Indy套接字源代码本身中搜索解决方案。请帮帮我!
更新1
C#码。在本例中,我是从WPF应用程序发送的。逻辑上,在UWP中如何使用流几乎是一样的,只使用StreamSocket和DataWriter。
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lenghtPrefix = BitConverter.GetBytes(byteMessage.Length);
Byte[] concatedData = new byte[lenghtPrefix.Length + byteMessage.Length];
lenghtPrefix.CopyTo(concatedData, 0);
byteMessage.CopyTo(concatedData, lenghtPrefix.Length);
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(concatedData);
writer.Flush();
stream.Close();
client.Close();但我们也尝试过这样的解决方案:
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lenghtPrefix = BitConverter.GetBytes(byteMessage.Length);
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect(hostTextBox.Text, int.Parse(portTextBox.Text));
socket.Send(lenghtPrefix, SocketFlags.None);
socket.SendBufferSize = byteMessage.Length;
socket.Send(byteMessage, SocketFlags.None);
socket.Close();服务器端的Pascal代码,等待流。以这种方式接收是至关重要的,因为软件的其他模块(也是使用Indy10编写的Pascal )以这种方式与服务器通信。
function Receive(const AContext: TIdContext): string;
var
Stream: TMemoryStream;
begin
try
Result := '';
Stream := TMemoryStream.Create;
if AContext.Connection.Connected then
AContext.Connection.IOHandler.ReadStream(Stream, -1, False);
finally
Result := UnPackStream(Stream);
Stream.Free;
end;
end;发布于 2016-07-06 19:12:50
最后,这里是解决办法。我们花了一整天的时间。我们使用Synapse套接字作为参考。最后,这里是UWP下的代码,我们也在其他桌面项目(WPF、Winforms)中测试了它(使用TcpClient和NetworkStream)。BitConverter和用数字作为空洞流的前缀无效,因为Indy以二进制格式等待长度,因此字节数组必须包含表示二进制长度的值。,我希望它能帮助其他有类似问题的人!
Windows.Networking.Sockets.StreamSocket socket = new Windows.Networking.Sockets.StreamSocket();
Windows.Networking.HostName serverHost = new Windows.Networking.HostName(hostTextBox.Text);
string serverPort = portTextBox.Text;
await socket.ConnectAsync(serverHost, serverPort);
//Write data to the server.
DataWriter writer = new DataWriter(socket.OutputStream);
byte[] data = Encoding.Unicode.GetBytes(messageTextBox.Text);
byte[] size = new byte[4];
ushort x = (ushort)(data.Length >> 16);
ushort y = (ushort)(data.Length);
size[0] = (byte)(x / 256);
size[1] = (byte)(x % 256);
size[2] = (byte)(y / 256);
size[3] = (byte)(y % 256);
writer.WriteBytes(size);
writer.WriteBytes(data);
await writer.StoreAsync();
await writer.FlushAsync();
writer.DetachStream();
//Read response.
var bytes = new byte[4];
DataReader reader = new DataReader(socket.InputStream);
await reader.LoadAsync(4);
reader.ReadBytes(bytes);
int length = bytes[0] * 256 * 256 * 256 + bytes[1] * 256 * 256 + bytes[2] * 256 + bytes[3];
byte[] dat = new byte[length];
var count = await reader.LoadAsync((uint)length);
reader.ReadBytes(dat);
responseTextBlock.Text = Encoding.Unicode.GetString(dat);
reader.DetachStream();
socket.Dispose();发布于 2016-07-06 16:30:17
在Indy中调用TIdIOHandler.ReadStream()时,如果AByteCount是-1而AReadUntilDisconnect是False,ReadStream()将读取前4个字节(Int32)或8个字节(Int64) (取决于TIdIOHandler.LargeStream属性的值),并按网络字节顺序(大端)将它们解释为整数,然后读取由该整数指定的字节数(如果大于0)。
第一个C#示例的主要问题是您使用的是一个StreamWriter,它是为发送文本而设计的,而不是二进制数据。如果您尝试用Byte[]来编写一个StreamWriter数组,它将不会按原样发送,它将被格式化为与Indy不兼容的文本表示形式。您不需要StreamWriter,您可以按原样使用NetworkStream,它有一个用于Byte[]数据的Write()方法。或者使用BinaryWriter。
这两个C#示例的另一个问题是,您在使用BitConverter时没有考虑到endian。它的GetBytes(Int32)方法在与调用机器的体系结构相同的端点中创建一个字节数组。Windows主要是一个小终端环境,但是ReadStream()需要大端字节中的整数字节.
尝试更像这样的东西:
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lengthPrefix = BitConverter.GetBytes(byteMessage.Length);
if (BitConverter.IsLittleEndian)
Array.Reverse(lengthPrefix);
NetworkStream stream = client.GetStream();
stream.Write(lengthPrefix, 0, lengthPrefix.Length);
stream.Write(byteMessage, 0, byteMessage.Length);
stream.Close();
client.Close();或者这个:
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lengthPrefix = BitConverter.GetBytes(byteMessage.Length);
if (BitConverter.IsLittleEndian)
Array.Reverse(lengthPrefix);
NetworkStream stream = client.GetStream();
BinaryWriter writer = new BinaryWriter(stream);
// BinaryWriter.Write(Int32) writes in little-endian only,
// so you still need to use Write(Byte[]) for the length value...
writer.Write(lengthPrefix);
writer.Write(byteMessage)
writer.Flush();
stream.Close();
client.Close();https://stackoverflow.com/questions/38208760
复制相似问题