2013-05-25 24 views
5

我工作的一個相當簡單的客戶端/服務器應用程序,並有一些麻煩,從使用的Winsock API提供的recv客戶端接收TStringStream。
我不斷收到此錯誤:'訪問衝突在0x00000000:讀取地址0x00000000'。
客戶端只將文本複製到TStringStream中,獲取它的長度並將其發送到服務器。服務器然後接收流並輸出它的文本。 下面是一些抽象的代碼提取。當使用(winsock's)recv接收到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

+0

如果你正在製作一個簡單的客戶端/服務器應用程序,爲什麼不去Delphi DataSnap? – Peter

+0

我使用的是winsock,因爲我需要演示socket如何工作。 –

+0

使用Indy或Synapse等更高級別的庫將使您的生活更輕鬆,並且可以節省時間:) – mjn

回答

7

您正在傳入recv指向TStringStream對象本身,而不是其數據緩衝區。這就是對象被破壞的原因。使用Memory財產:recv(connfd, inBuf.Memory^, inLen, 0)

發送同樣的道理:從數據流發送數據,而不是數據流對象(你的SSend中的sizeof(msg)只返回一個指針的大小)。

+0

線'的recv(connfd,inBuf.Memory,inLen,0);'給出了一個編譯錯誤:in.Buf是一個常量表達式,而需要VAR –

+0

對不起,應該是'inBuf.Memory ^'(該真正的「var」是由「內存」指向的內存區域)。我已經在答案中糾正了這一點。 – Inspired

+0

是的,我只是想出了,也:)將行改爲'rec:= recv(connfd,inBuf.Memory ^,inLen,0);''發送(sock,msg.Memory ^,msg.Size, 0);'感謝您的幫助! –