Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi TStringStream在使用(winsock';s)recv接收时损坏?_Delphi_Stream_Winsock_Recv - Fatal编程技术网

Delphi TStringStream在使用(winsock';s)recv接收时损坏?

Delphi TStringStream在使用(winsock';s)recv接收时损坏?,delphi,stream,winsock,recv,Delphi,Stream,Winsock,Recv,我正在开发一个相当简单的客户机/服务器应用程序,使用winsock API提供的recv从客户机接收TStringStream时遇到一些问题。 我一直收到以下错误:“0x00000000处的访问冲突:读取地址0x00000000”。 客户端只将文本复制到TStringStream中,获取其长度并将其发送到服务器。然后,服务器接收流并输出其文本。 下面是一些抽象代码摘录 { the server's part } inBuf := TStringStream.Create; { MAKE THIS

我正在开发一个相当简单的客户机/服务器应用程序,使用winsock API提供的recv从客户机接收TStringStream时遇到一些问题。
我一直收到以下错误:“0x00000000处的访问冲突:读取地址0x00000000”。
客户端只将文本复制到TStringStream中,获取其长度并将其发送到服务器。然后,服务器接收流并输出其文本。 下面是一些抽象代码摘录

{ the server's part }
inBuf := TStringStream.Create;
{ MAKE THIS SOCKET A PASSIVE ONE }
  listen(serversock, LISTENQ);
{ ACCEPT CONNECTION ON serversock FROM cliaddr -> CONNECTED SOCKET = connfd }
connfd := accept(serversock, @cliaddr, @len);
recv(connfd, inLen, sizeof(inLen), 0);
//up to here everything is fine with the strem: 
//Size = InLen, Position = 0, all bytes are '0'
rec := recv(connfd, inBuf, inLen, 0);
//rec = inLen, which is fine
//now this: inBuf: FMemory $1, FSize 9 (no matter how long the msg is)
// FPosition 7077987 and FBytes: many many random
DebugOutput(inBuf.DataString); //the error is thrown here
其中connfd是连接的套接字,servsock是侦听套接字,inLen是包含inBuf长度的基数,inBuf是全局TStringStream。rec是一个基数,包含recv接收的字节数

{ the client's send function }
function SSend(sock :TSocket; addr :sockaddr_in; msg :TStringStream) :Integer;
var
  len: Cardinal;
begin
  len := msg.Size;

  send(sock, len, sizeof(len), 0);
  msg.Seek(0,0);
  send(sock, msg, sizeof(msg), 0);

  Result := 0;
end;
以及客户对SSend的呼叫:

{ CREATE (OUTPUT)STREAM }
s := TStringStream.Create;
  s.WriteString(_input.Text);
  //_input is a TMemo with text, let's say, ´hello´
SSend(client, servaddr, s);
//client is a TSocket
提前谢谢你的帮助

p1.e

您正在向
recv
传递指向
TStringStream
对象本身的指针,而不是指向其数据缓冲区的指针。这就是对象损坏的原因。使用
Memory
属性:
recv(connfd,inBuf.Memory^,inLen,0)


发送也一样:从流发送数据,而不是流对象(
sizeof(msg)
SSend
中返回指针的大小)。

如果您正在制作一个简单的客户端/服务器应用程序,为什么不使用Delphi DataSnap?我使用的是winsock,因为我需要演示插座是如何工作的。使用像Indy或Synapse这样的更高级别的库会让你的生活更轻松,并且可以节省时间:)我通常是这样做的:)但是,对于学校来说,我需要展示插座是如何工作的。因此,我使用基本的winsock例程给出了一个编译错误:in.Buf是一个常量表达式,而var是必需的。抱歉,它应该是
inBuf.Memory^
(真正的“var”是
Memory
指向的内存区域)。我在回答中已经纠正了这个问题。是的,我也刚刚发现:)将行更改为
rec:=recv(connfd,inBuf.Memory^,inLen,0)
发送(sock,msg.Memory^,msg.Size,0)谢谢你的帮助!TStringStream对象的容量是否不需要首先设置以防止UB?是的,它肯定会。我想代码只是省略了,但容量设置正确(在recv
之前有一条注释
Size=InLen
)。