【问题标题】:Socket programming beginners questions套接字编程初学者问题
【发布时间】:2023-03-27 09:12:01
【问题描述】:

我对整个套接字和服务器开发真的很陌生,我还不熟悉它是如何工作的。

我做了一个简单的 Flash 应用程序,它需要与套接字通信, 有了这个,我使用了一个支持 AS3 并在“Red Tamarin”上工作的套接字,

那我就直奔主题了:

我目前有一个始终运行 socket.receive() 的循环 它会响应甚至显示我从 Flash 应用程序发送的文本。

我的目标是做一个简单的在线Flash游戏, 大概是使用SQL/SQLite来保存信息并导出给玩家,

我不明白我怎么能把它带到那里..

我认为我需要做的是这样的:

在服务器端:

  • 只要服务器处于活动状态,就会有一个循环运行,该循环应始终检查它与客户端的每个连接并等待来自客户端的命令,例如登录、更新玩家位置、断开连接、请求对象列表在给定的位置

客户端:

  • 根据动作向服务器发送信息,例如当玩家移动时,以类似的方式向服务器发送新位置:“MovePlayer[name][x][y]”

我的计划真的应该是这样吗? 关于发送的实际信息,我很好奇,不断发送服务器字符串数据是否有效? (这是我习惯使用的,而不是一些奇怪的字节和东西)

提前致谢!

【问题讨论】:

  • 除非游戏本质上是多人游戏,否则您可能不希望每个客户端都告诉服务器它所做的一切......这根本不能很好地扩展。
  • 如果你在 c++ 中的套接字中做任何事情,了解那些“奇怪的字节和东西”将是一个好主意
  • 如果没有那样的交流,你还怎么更新这些东西呢?
  • 在大多数情况下,您可以将要在字符串中发送的大量信息压缩成一个字节。发送的数据越少越好。

标签: c++ actionscript-3 sockets server-side


【解决方案1】:

你在正确的轨道上。但我鼓励您首先定义一个通信协议。您可以从定义命令的外观开始。例如:

COMMAND <space> PARAM1 <space> PARAM2 <line-break>

关于协议定义的一些注意事项:

  1. 如果PARAM1 是一个字符串并且包含空格怎么办?你怎么知道每个参数的开始和结束?
  2. 您的参数还可以包含换行符。
  3. 如果您的客户端应用程序是由您的客户端安装的,则他们需要不时对其进行更新。更复杂的是,即使您更改了协议,他们也可能运行旧版本并期望它能够工作。这需要协议版本控制。如果您需要用户交互来更新应用程序的客户端部分,请记住这一点。

对于您的方案,这些是我能想到的最基本的考虑因素。可能还有其他重要的考虑因素,但其中大部分取决于您的游戏如何运作。如果您认为我忘记了 OP 应该考虑的内容,请随时修改我的列表。

定义命令的外观后,记录您认为您的应用程序需要的所有命令。不要分离命令的定义,除非它对您的某些操作来说太复杂或太长。尽量保持简单。

现在回到你的问题:

我的计划真的应该是这样吗?

是的。这正是它应该的样子。

关于发送的实际信息,我很好奇,不断发送服务器字符串数据是否有效? (这是我习惯使用的,而不是一些奇怪的字节和东西)

这取决于许多因素:

  1. 您使用的是哪种协议(TCP、UDP 等);
  2. 并发客户端数;
  3. 处理命令的平均时间;
  4. 你们会向其他玩家广播更新吗?
  5. 您是如何实现服务器应用程序的;
  6. 物理约束:
    1. 硬件:CPU、内存等;
    2. 网络:带宽、延迟等;


(来源:it20.info)

【讨论】:

  • 您好,首先非常感谢您的出色回答!我现在将开始计划整个事情,很高兴知道我在正确的轨道上:) - 关于实际协议,将文本转换为二进制,将其发送到服务器并将其转换为文本听起来是否正确在服务器端?还是您认为按原样发送会更好?
  • 不客气。您可以将所有内容作为纯文本传输,但考虑到性能而设计的协议始终使用二进制数据作为数字/标志。字符串保留为字符串,除非需要编码/解码。如果您打算通过 TCP 使用加密技术,那么 SSL/TLS 就足够了。无论哪种方式,了解您的数据如何在二进制级别存储和传输总是很积极的。见Application Protocol Design 和Endianness in networking。
  • 好的,再次感谢嘿嘿,现在的最后一个问题是:我设置新的套接字,绑定它,然后执行listen(),当检测到连接时,我使用accept()并添加新套接字连接到一组活动连接,我目前的问题是我不明白我到底需要如何接受命令,我应该在我拥有的每个套接字上分别监听命令吗?还是应该只在主要的,然后以某种方式检测是谁发送的?我的想法是在每个连接上继续运行接收(),看看我是否得到任何东西,但我不确定这是否是这样做的正确方法
  • 最基本和最简单的方法是分别处理每个套接字上的事件。您还可以使您的套接字成为非阻塞的,这样您就可以在一个线程中处理其中的许多。还有其他方法可以处理他们的事件,例如:select、poll、epoll、kqueue 等。或者您可以使用抽象出大部分相关复杂性的库,例如 libevent,或Boost.Asio。自然的过程是学习基本处理,然后转到图书馆。
【解决方案2】:

看看这个 https://code.google.com/p/spitfire-and-firedrop/

在那里你将看到使用 redtamarin 构建套接字服务器的基础

具体看 https://code.google.com/p/spitfire-and-firedrop/source/browse/trunk/spitfire/src/spitfire/Server.as

详情如下,redtamarin 基本上使用阻塞套接字和 select() 最大硬编码 FD_SETSIZE 为 4096 看: https://code.google.com/p/redtamarin/wiki/Socket#maxConcurrentConnection

所以在你的服务器循环中发生了什么

你基本上有一个套接字对象数组

您每 x 毫秒循环一次,并针对每个套接字 你问能不能看懂

如果你可以在套接字上读取,然后你比较这个套接字 obj 是否是服务器 如果是服务器,则意味着您有新连接 如果不是,则意味着客户端尝试向您发送数据,因此您读取了此数据 然后将其传递给“解释器”

稍后在同一个循环中检查套接字 obj 是否仍然有效 如果你能写信给它 如果您可以编写并且套接字对象不是服务器 然后你可以向客户端发送数据

这里是 C 中的等效代码供参考 http://martinbroadhurst.com/source/select-server.c.html http://www.lowtek.com/sockets/select.html

对于一个非常基本的示例,请查看 socketpolicyd

https://code.google.com/p/spitfire-and-firedrop/wiki/socketpolicyd https://code.google.com/p/spitfire-and-firedrop/source/browse/trunk/socketpolicyd/src/spitfire/SocketPolicyServer.as

并将实现与 Perl 和 PHP 进行比较 http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多