首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Indy10与System.Net.Sockets的联网

Indy10与System.Net.Sockets的联网
EN

Stack Overflow用户
提问于 2016-07-05 16:53:25
回答 2查看 610关注 0票数 0

我和我的合作伙伴正在从事一个项目,我的合作伙伴正在Pascal中开发,并使用Indy10套接字进行网络连接,我正在C#下开发一个UWP项目。因此,对于网络,我必须使用streamsocket命名空间。

问题是,我的合作伙伴使用带有-1和假参数的ReadStream方法,这意味着接收流的长度不确定。因此,我必须从流中的数据(例如,使用BitConverter.GetBytes类)发送一个长度前缀(在本例中我使用的是DataWriter方法),继续使用数据本身。但是Indy10套接字没有收到任何信息。它看起来像是在等待包裹,或者我不知道。

有人碰到这个问题了吗?请帮帮忙,我们已经处理了大约两周了。我在StackOverflow上读过所有类似的问题,这是一个关于使用框架和分隔的博客。在Indy套接字源代码本身中搜索解决方案。请帮帮我!

更新1

C#码。在本例中,我是从WPF应用程序发送的。逻辑上,在UWP中如何使用流几乎是一样的,只使用StreamSocket和DataWriter。

代码语言:javascript
复制
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();

但我们也尝试过这样的解决方案:

代码语言:javascript
复制
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 )以这种方式与服务器通信。

代码语言:javascript
复制
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;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-06 19:12:50

最后,这里是解决办法。我们花了一整天的时间。我们使用Synapse套接字作为参考。最后,这里是UWP下的代码,我们也在其他桌面项目(WPF、Winforms)中测试了它(使用TcpClientNetworkStream)。BitConverter和用数字作为空洞流的前缀无效,因为Indy以二进制格式等待长度,因此字节数组必须包含表示二进制长度的值。,我希望它能帮助其他有类似问题的人!

代码语言:javascript
复制
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();
票数 0
EN

Stack Overflow用户

发布于 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()需要大端字节中的整数字节.

尝试更像这样的东西:

代码语言:javascript
复制
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();

或者这个:

代码语言:javascript
复制
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();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38208760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档