- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在编写的程序有一个小问题。
首先让我解释一下它应该实现什么。
它与聊天程序非常相似,因此从根本上来说,它具有一个信息类(我称它为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)
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}
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/
我目前正在编写的程序有一个小问题。 首先让我解释一下它应该实现什么。 它与聊天程序非常相似,因此从根本上来说,它具有一个信息类(我称它为Packet),该信息类存储有关某些内容的数据,这些数据发生在客
同一角色的多个角色实例是否可以通过从 RoleEnvironment 获取所有这些实例监听的特定端点的 VIP(虚拟 IP)地址来相互通信?如果是这样,则返回的 VIP 可以负载平衡到调用者(Role
概述 ET框架的消息机制贯彻始终,包含Entity消息(Awake,Update ...),自定义(Customer)消息,网络消息等。而ET系统的进程包含了客户端、Gate等各种类型的服务器
我正在尝试设置一个 Docker Swarm,其中容器使用 Overlay Network 进行通信,但我可以让它工作 我正在使用包含 Docker Engine 1.12.1 的 HypriotOS
我是一名优秀的程序员,十分优秀!