2013-05-25 30 views
5

Tôi đang làm việc trên ứng dụng Client/Server khá đơn giản và gặp sự cố khi nhận TStringStream từ ứng dụng khách bằng cách sử dụng recv do winsock API cung cấp.
Tôi tiếp tục nhận được lỗi này: 'vi phạm truy cập tại 0x00000000: đọc địa chỉ 0x00000000'.
Máy khách chỉ sao chép văn bản vào TStringStream, nhận được chiều dài và gửi nó đến máy chủ. Sau đó, máy chủ sẽ nhận Luồng và xuất ra văn bản. Dưới đây là một số trích đoạn mã trừu tượng.TStringStream bị hỏng khi nhận được sử dụng recv (winsock's)?

{ 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 

nơi connfd là ổ cắm kết nối servsock là ổ cắm nghe, inLen là một hồng y có chứa chiều dài của inBuf, inBuf là một TStringStream toàn cầu. rec là một hồng y chứa số byte nhận được bằng 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; 

và cuộc gọi của khách hàng để 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 

Nhờ sự giúp đỡ trước!
p1.e

+0

Tại sao bạn không truy cập Dữ liệu Delphi nếu bạn đang tạo một ứng dụng khách/máy chủ đơn giản? – Peter

+0

Tôi đang sử dụng winsock, vì tôi cần chứng minh cách ổ cắm hoạt động. –

+0

Sử dụng thư viện cấp cao hơn như Indy hoặc Synapse sẽ làm cho cuộc sống của bạn dễ dàng hơn và có thể tiết kiệm thời gian :) – mjn

Trả lời

7

Bạn đang chuyển thành recv một con trỏ đến TStringStream chính đối tượng đó, không phải vào bộ đệm dữ liệu của đối tượng đó. Đó là lý do tại sao đối tượng bị hỏng. Sử dụng tài sản Memory: recv(connfd, inBuf.Memory^, inLen, 0).

Điều tương tự cũng xảy ra khi gửi: gửi dữ liệu từ luồng, chứ không phải đối tượng luồng (sizeof(msg) trong số SSend trả lại kích thước của con trỏ).

+0

Dòng 'recv (connfd, inBuf.Memory, inLen, 0);' đưa ra một lỗi biên dịch: in.Buf là một biểu thức liên tục, trong khi một var là bắt buộc –

+0

Xin lỗi, nó phải là 'inBuf.Memory ^' ("var" thực là vùng bộ nhớ được chỉ bởi 'Memory'). Tôi đã sửa lỗi này trong câu trả lời. – Inspired

+0

Vâng, tôi cũng chỉ ra rằng, quá :) đã thay đổi các dòng thành 'rec: = recv (connfd, inBuf.Memory ^, inLen, 0);' và 'send (sock, msg.Memory ^, msg.Size, 0); 'Cảm ơn bạn đã trợ giúp! –

Các vấn đề liên quan