5

私はかなり単純なクライアント/サーバー アプリケーションに取り組んでおり、winsock API によって提供されるrecvを使用してクライアントから TStringStream を受信する際に問題があります。
「0x00000000 でのアクセス違反: アドレス 0x00000000 の読み取り」というエラーが表示され続けます。
クライアントはテキストを TStringStream にコピーするだけで、その長さを取得してサーバーに送信します。次に、サーバーは Stream を受け取り、そのテキストを出力します。いくつかの抽象的なコードの抜粋の下。

{ 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

4

1 に答える 1

7

データバッファーではなく、オブジェクト自体へrecvのポインターに渡しています。TStringStreamそのため、オブジェクトが破損します。使用Memoryプロパティ: recv(connfd, inBuf.Memory^, inLen, 0)

同じことが送信にも当てはまります。ストリームオブジェクトではなく、ストリームからデータを送信sizeof(msg)します(SSendポインターのサイズだけを返します)。

于 2013-05-25T12:06:10.093 に答える