gpt4 book ai didi

delphi - 网络通信-某些信息无法到达服务器

转载 作者:行者123 更新时间:2023-12-03 18:38:06 26 4
gpt4 key购买 nike

我目前正在编写的程序有一个小问题。

首先让我解释一下它应该实现什么。

它与聊天程序非常相似,因此从根本上来说,它具有一个信息类(我称它为Packet),该信息类存储有关某些内容的数据,这些数据发生在客户端窗口中。该程序本身包括两个不同的客户端窗口和一个服务器窗口。 (还有一个窗口可以打开每个窗口,但这现在并不重要。)

因此,客户更改了其Window上的某些内容,然后按send。

然后我的数据包将存储所有这些信息。它由一个昵称,一个文本,一些不同的数字值(基本上是骰子滚动结果)和一个“种类”变量组成。

有三种不同的消息,此“数据包”能够发送。


普通短信(完美运行)。
骰子消息,由3个骰子结果,一个难度值和一个人才值组成。
另一个骰子消息,这次仅包含一个骰子结果。


每当发送一条消息(并因此被服务器接收)时,程序就会读出该消息是什么类型的消息(通过种类变量),并根据消息的内容启动不同的步骤来处理该消息。

聊天消息仅在聊天中显示,并发送到每个客户端以显示在此处。这有效,没有任何错误或其他东西。

骰子消息都具有特殊的形状来显示。
它基本上是按照这种形状生成的聊天消息,以显示掷骰是否成功。



现在是我的问题:

我在LAN版本(使用我的语言环境IP)中测试了该程序,并且运行良好。没问题,没有错误。

但是现在我请一个朋友帮助我通过互联网对其进行测试。
Portforwarding工作正常,客户端可以连接。

现在用于发送消息。
Chatmessage:工作正常
Dice1-Message:仅发送昵称和两个骰子结果。第三个骰子结果未显示,所有其他信息仅在该处留下空白。
第二个骰子消息也是如此。它仅显示骰子结果和昵称,而不显示任何其他信息。

如果有帮助的话,该程序是用Delphi 6.0编写的(是的,有点老了,但是我已经习惯了该程序,但是我对编程还不太了解。.所以我用它来学习基础知识和编写我的程序。第一个更大的程序,像那样的程序。)

数据包本身的定义如下:

type
TPacket = Record
Nickname : string[255];
Text : string[255];
OtherInfo: VarType;
end;


等等
然后,消息引用如下信息:

ServerSocket.Socket.ReceiveBuf (Packet, SizeOf(Packet));

MemMessage.Lines.Add(Packet.Nickname + 'succeeded his dice roll for ' + Packet.Talent + 'Restofmessage ' + Packet.OtherInformation)


所以。就是这样。我希望那里的任何人都知道问题出在哪里(或者在这种情况下更好的是局域网和Internet之间的导致问题的区别是什么),并且知道一种可以帮助我解决此问题的方法。

在此先谢谢〜

PS:服务器只是简单地获取信息,以相同的方式显示信息,任何客户端都会这样做,然后将其直接发送给每个客户端,后者将接收并显示信息。以防万一这很重要。



编辑:

嗯,我认为这些信息确实很好,因为“其他信息”确实不一样。

好的〜更多详细信息:)

“其他信息”的类型均为字符串[255],其中之一是布尔值。

Dice1-Type使用以下内容:

昵称,结果1,结果2,结果3,难度,技能点,才华(只是骰子掷骰测试成功或失败的才华的名称)和一个布尔值,称为“成功”。

Dice2使用:

昵称,结果,难度,人才(人才的名称。不要误认为价值^^),TalentPoints(基本上是人才的价值减去掷骰子的难度)以及布尔值“成功”以及称为“种类”的字符串[255]。种类的功能已在上面说明。

至于协议,我认为不使用任何特殊协议。

我只是通过SendBuf和ReceiveBuf发送整个类TPacket。
我刚开始编程,所以很抱歉,我无法提供更多信息:/

让我为您提供该过程的代码,服务器用于接收和重定向TPacket。

我希望我不会犯任何错误,因为我是用德语编写程序,所以我现在必须翻译它。

procedure TFormServer.ServerSocketClientRead (Sender:TObject; Socket: TCustomWinSocket);
var
Message : TPacket;
i : ShortInt;
begin
{receive Message}
Socket.ReceiveBuf (Message, SizeOf(Message))

{checking, what kind the message is of}
if Message.Kind = 'Chat' then begin
MemMessage.Lines.Add ('By' + Message.Nickname + ': ' + Message.Text);

{Redirecting to other clients}
with ServerSocket.Socket do begin
for i := 0 to ActiveConnections -1 do
Connections[I].SendBuf(Message, SizeOf(Message))
end;
end;


if Message.Kind = 'DiceRoll_1' then begin
if Message.Success = true
then MemMessage.Lines.Add (Message.Nickname + ' succeeded his Dice Roll for ' + Message.Talent + ' (Difficulty: ' + Message.Difficulty + ') with the results: (' + Message.Result1 + '/' + Message.Result2 + '/' + Message.Result3 + '), Skill lvl: ' + Message.Skillpoints);

//The Message should look like that
{Dummy succeeded his Dice Roll for climbing (Difficulty: 4) with the results: (12/14/13), Skill lvl: 8}

//For Comparison, the buggy message looks like that
{Dummy succeeded his Dice Roll for (Difficulty: ) with the results: (12/14/ ), Skill lvl: }
else {The same as when it succeeded, just saying it did 'not' succeed..}


{redirection}
with ServerSocket.Socket do begin
for i := 0 to ActiveConnections -1 do
Connections[i].SendBuf (Message, SizeOf(Message))
end;

end; {if kind = DiceRoll_1}

{Same goes for the DiceRoll_2 now. This time it uses: Message.Nickname, Message.Talent, Message.Difficulty, Message.Result, Message.TalentPoints, Message.Success}


现在再次说明我的TPacket的整个声明。可能很重要

type    TPacket = Result
Kind : string[255];
Nickname : string[255];
Text : string[255];
Result : string[255];
Result1 : string[255];
Result2 : string[255];
Result3 : string[255];
Difficulty : string[255];
Talent : string[255];
Skillpoints : string[255];
TalentPoints: string[255];
Succeed : boolean;
end;


我希望这使它更容易理解。
我想我不太会解释:/

但是,感谢您在这里对我的欢迎,希望我对您没有麻烦,并且也可以在一个或另一个案例中为您提供帮助!

最佳答案

嗯..如果它是我正在考虑的组件,则ClientRead事件被引发了一个充满数据的完整消息,这并不是锁。

在这种情况下,您需要在TCP之上的协议以允许消息传输。 TCP本身不能传输消息,只能传输字节流。

TCustomWinSocket文档,(我的斜体字):

'使用ReceiveBuf从Windows套接字对象的OnSocketEvent事件处理程序或套接字组件的OnRead或OnClientRead事件处理程序中的套接字连接中读取。

ReceiveBuf返回实际读取的字节数(可能小于调用中请求的字节数)。

如果未读取任何字节,则ReceiveBuf返回–1。

因此,仅声明超大缓冲区并始终转移批次以试图避免解析接收到的数据的狡猾计划没有用。

您需要正确执行。设计一个协议,无论ClientRead()事件是触发一条完整消息,部分消息,组合消息还是每次触发一个字节,都将起作用。我的首选设计是将'PDU'类与'byteLoad(thischar:char):boolean;'结合使用。使用内部状态机处理协议的方法,使用corect数据加载字段,并且仅在组装了完整的消息后才返回true。在每个ClientRead调用中,我都对每个接收的字节进行迭代,并调用'byteLoad',直到它返回true,然后处理PDU(可能是通过将其排队的地方),创建另一个PDU并开始加载它。

请注意,由于您使用的是异步非线程TServerSocket选项,因此必须将所有此类特定于客户端的数据(例如PDU实例)或必须在ClientRead调用之间保留的任何其他数据存储为传入的TCustomWinSocket实例的字段。这意味着要么是TCustomWinSocket后代来保存此数据,要么使用基本TCustomWinSocket的'data'属性来保存另一个对象或记录。这些东西通常是在OnConnected事件中创建/初始化/加载的。当心TCustomWinSocket在断开连接时的行为-我有一种奇怪的感觉,它试图释放数据字段中的任何非nil指针-您可能不希望这样做。

关于delphi - 网络通信-某些信息无法到达服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10322012/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com