我正在尝试通过网络将mp3文件发送到由媒体播放器播放的服务器。我到目前为止的代码适用于字符串,但不适用于文件。有人能告诉我我做错了什么吗?
这是源代码
客户端:
procedure TForm1.Button1Click(Sender: TObject);
var
MyStream : TFileStream;
MP3 : TFileName;
Len : Int64;
begin
MP3 := GetCurrentDir + '\Clocks.mp3';
MyStream := TFilestream.Create(MP3, fmOpenRead);
try
Len := Length(MP3);
MyStream.WriteBuffer(Len, SizeOf(Len));
MyStream.WriteBuffer(Pointer(MP3)^, Len * SizeOf(MP3));
MyStream.Position := 0;
TcpClient1.Active := True;
TcpClient1.SendStream(MyStream);
TcpClient1.Active := False;
finally
MyStream.Free
end;
end;
服务器:
procedure TForm1.TcpServer1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
MP3 : TFileName;
Len: Int64;
begin
//Receives the message from the client
ClientSocket.ReceiveBuf(Len, SizeOf(Len),0);
SetLength(MP3, Len);
ClientSocket.ReceiveBuf(Pointer(MP3)^,Len * SizeOf(MP3), 0);
MediaPlayer1.FileName := MP3;
MediaPLayer1.Open;
MediaPlayer1.Play;
end;
问题在程序尝试编写流时开始,因此我甚至不确定接收端是否正常工作
聚苯乙烯。我是一名初学者
答案 0 :(得分:2)
首先,您要发送宽带,这意味着您必须使用:
Len :=Length(mp3) * SizeOf(Char);
其次,你不需要演员。这应该没问题:
myStream.Write(mp3[1],Len);
第三,如果tcpSocket是非阻塞的,那么在发送流之后你不能直接禁用它,这会在连接开始之前切断连接。使用事件来了解数据的发送时间。
要避免这一切,请在流上使用TReader和TWriter。这样你就不必关心双方的字符串数据大小,只需要关注流大小。
提示:首先发送一个魔术值(一个常量值),这样就可以检查另一侧是否是有效的数据包。
这是你可以做到的一种方式:
Procedure TForm1.WriteMP3File(aFilename:string);
var
mData: TMemoryStream;
mFile: TFilestream;
mWriter: TWriter;
Begin
mData:=TMemoryStream.Create;
try
mFile:=TFileStream.Create(aFilename,fmOpenRead);
try
mWriter:=TWriter.Create(mData);
try
// Write header code, any number will do
mWriter.WriteInteger($BABE);
// Write the filename
mWriter.WriteString(ExtractFileName(aFilename));
//Write size of MP3 file
mWriter.WriteVariant(mFile.Size);
//Push all data into the mData stream
mWriter.FlushBuffer;
//Append MP3 file
mData.CopyFrom(mFile,mFile.Size);
finally
mWriter.Free;
end;
mData.Position:=0;
socket.sendstream(mData);
finally
mFile.Free;
end;
finally
mData.Free;
end;
end;
阅读它是在服务器上反向完成的:
Procedure TForm1.ReadMP3File(aMp3PlayPath:String;aStream:TStream);
var
mReader: TReader;
mFileData: TFileStream;
mName: String;
mSize: Int64;
Begin
try
mReader:=TReader.Create(aStream);
try
if mReader.ReadInteger=$BABE then
Begin
mName:=mReader.ReadString;
mSize:=mReader.ReadVariant;
end else
raise exception.Create('Invalid datapackage error');
finally
mReader.Free;
end;
if mSize>0 then
Begin
mFileData:=TFileStream.Create(aMp3PlayPath + mName,fmCreate);
try
mFiledata.CopyFrom(aStream,mSize);
finally
mFiledata.Free;
end;
end;
//Now you can play the file
finally
//Release stream or do it elsewhere
aStream.Free;
end;
end;
答案 1 :(得分:0)
首先是这段代码:
MyStream.WriteBuffer(Len, SizeOf(Len));
MyStream.WriteBuffer(Pointer(MP3)^, Len * SizeOf(MP3));
在此您尝试更改MP3文件内容,它会损坏您的mp3文件。幸运的是,您将文件打开为fmOpenRead
,这就是MyStream.WriteBuffer
失败的原因。
如果要将文件名发送到服务器,则必须单独发送(例如使用TTcpClient.SendBuf
。
在服务器端,您当前只读取文件名并忽略文件内容本身。
ClientSocket.ReceiveBuf(Len, SizeOf(Len),0); // this reads length of the filename
SetLength(MP3, Len);
ClientSocket.ReceiveBuf(Pointer(MP3)^,Len * SizeOf(MP3), 0); // this reads filename itself
// Now you should receive file contents itself and store it on the server
将文件存储在服务器上后,您可以使用MediaPlayer1播放该文件。如果您不将文件存储在服务器中,则只能在服务器和客户端位于同一台计算机上时播放该文件(除非媒体播放器使用url或网络路径作为FileName)。