繁体   English   中英

关于在 java 中使用 sockets 开发服务器

[英]About developing servers with sockets in java

简而言之,我有两个课程,它们是:

public final class ServerMain
{

      static List<Table> s_AvailableGameTables = new Vector<Table>(); 
      static List<Table> s_OccupiedGameTables = new Vector<Table>(); 
      static List<ServerThread> s_PlayersOnServer = new Vector<ServerThread>();
...
}
class ServerThread extends Thread{
...}

ServerMain是服务器本身,它通过为刚刚连接到ServerMain的每个用户分配一个新的ServerThread来管理ServerThreads

我的问题很简单:

  1. 当我当前在特定的 ServerThread 中运行并且我想访问 serverMain 上的一些 static 列表并更新它们时,如果我已经在特定线程中“离开”了 ServerMain 的区域,我该怎么做在后台运行。 唯一的方法是持有从每个服务器线程到 papa ServerMain 的引用吗?

  2. 也许它会导致一些问题,好像代码的两个区域可以同时更新同一个列表 ServerMain 本身和现在知道谁是大老板的 ServerThread ?

  3. 一般问题:sockets 编程是指 UDP 还是 TCP?

我想听听一些好的建议。 提前致谢。

  1. 不,您可以像“正常”一样引用它。 从某种意义上说,实际上从不同的线程而不是不同的 object 引用事物没有语法变化。 现在,您可能需要同步对它的访问,但我并不认为这会改变引用事物的方式。
  2. 同步列表(最好使用 java.util.concurrent 包)。 确保表本身也是线程安全的。
  3. 也不是,套接字使用传输协议,但它可以是 UDP、TCP 或其他任何东西。 澄清一下,你不能仅仅通过说你正在使用一个套接字来确定正在使用什么传输协议。 您必须指定您实际使用的协议。

对于#1,您不需要实例来访问 ServerMain 的static成员,假设它们是可访问的(例如它们是public ),您可以将它们作为ServerMain.MyVar访问。

对于#2,是的,您需要考虑使用synchronized语句来防止多个线程同时写入列表,或者使用线程安全列表实现。

对于#3,术语“套接字编程”可以指 UDP 或 TCP。 您使用哪种类型的套接字将取决于您正在实现的应用程序类型。

  1. 如果您使用同步列表(即Vector ,java.util.concurrent package 中的列表之一,或者如果它更适合Collections.synchronizedList(list)
  2. Vector 已经“同步”,但请注意,您必须手动同步事务(即synchronized (vector) { vector.add(..); vector.remove(..); } )。 默认情况下,它采用的同步基本上阻止列表方法调用中断当前执行的用户定义事务和列表上当前执行的方法调用。 我建议使用Collections.synchronizedList(list)而不是Vector ,尽管它们都做同样的工作,真的。
  3. ServerSocket / Socket为 TCP, DatagramSocket为 UDP。

1)这是可能性之一。 一般来说,当您需要访问另一个 object 方法时,最好的方法是保留引用(直接或间接)。 Yet, as it is supposed that you'll only have a ServerMain object, you could try to declare static methods or use the singleton construction (private constructor, you can only access a getInstance() static method that returns a shared object).

2) 线程之间的访问同步是一个冗长的主题,已经写了很多关于它的书。 最简单的方法是使用synchronized方法(或块)并在内部执行所有种族敏感命令。 但请注意,这可能这些同步块稍后将成为您的主要瓶颈。 当你有更多的练习,研究java同步方法。

3)正如其他人 java 所说,您只需打开一个在给定端口号中侦听协议的套接字。 您可以决定是否希望它是 UDP 或 TCP。 当然,请记住,使用 UDP 可能您收到的消息将不完整,因此必须由您的代码处理。

1)这将是一种方式,并且可能是一种首选方式,尽管不一定是唯一的方式。

此外,引用不需要由 ServerThread 拥有。 由于 ServerMain 可能是 singleton,我发现在这种情况下,给 Singleton 一个引用自身的 static 变量是有意义的。 然后,从任何 ServerThread,你可以做

class ServerThread extends Thread
{
    public void someMethod()
    {
        ServerMain.serverMain.whatever();
    }
}

2)是的,这导致问题。 阅读Java Concurrency Trail ,特别是关于同步的部分。 这是一个过于广泛的主题,无法在此处的答案中轻松涵盖。 但要获得快速而肮脏的答案,请查看同步方法。 如果您只是使处理此列表访问的方法同步,那么它将是安全的。 当然,根据您的需要,锁定列表访问可能会剥夺线程的任何性能提升。

3)它不一定必须,但它通常会。 “TCP 套接字”比“UDP 套接字”更有可能,但两者都有效。 如果您想为整个长时间的交易提供专用且可靠的连接,您可能应该使用 TCP。 TCP 保证数据已被接收并按特定顺序接收。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM