简体   繁体   English

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

[英]About developing servers with sockets in java

I have two classes in short here they are:简而言之,我有两个课程,它们是:

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 is the server itself, and it manages the ServerThreads by allocating a new ServerThread for each user who has just connected to the ServerMain . ServerMain是服务器本身,它通过为刚刚连接到ServerMain的每个用户分配一个新的ServerThread来管理ServerThreads

My questions are simple:我的问题很简单:

  1. When I'm currently running in the specific ServerThread and I want to access some static lists on the serverMain and to update them how can I do that, if I've already "left" the area of the ServerMain while being in the specific thread which runs in the background.当我当前在特定的 ServerThread 中运行并且我想访问 serverMain 上的一些 static 列表并更新它们时,如果我已经在特定线程中“离开”了 ServerMain 的区域,我该怎么做在后台运行。 Is the only way is to hold a reference from each serverthread to papa ServerMain?唯一的方法是持有从每个服务器线程到 papa ServerMain 的引用吗?

  2. Maybe it can cause some problems as if at the same time two areas of the code can update the same list the ServerMain itself and the ServerThread which now knows who is the big boss around?也许它会导致一些问题,好像代码的两个区域可以同时更新同一个列表 ServerMain 本身和现在知道谁是大老板的 ServerThread ?

  3. General question: does sockets programming means UDP or TCP?一般问题:sockets 编程是指 UDP 还是 TCP?

I'd like to hear some good advice.我想听听一些好的建议。 Thanks in advance.提前致谢。

  1. No, you can reference it like 'normal'.不,您可以像“正常”一样引用它。 In the sense that there is no syntactic changes for actually referencing things from a different thread rather than a different object.从某种意义上说,实际上从不同的线程而不是不同的 object 引用事物没有语法变化。 Now, you may need to synchronize access to it, but I don't really see that as changing how you reference things.现在,您可能需要同步对它的访问,但我并不认为这会改变引用事物的方式。
  2. Synchronize the list (preferably use the java.util.concurrent package).同步列表(最好使用 java.util.concurrent 包)。 Make sure that the Tables themselves are thread-safe as well.确保表本身也是线程安全的。
  3. Neither, a socket uses a transport protocol, but it could be UDP, TCP, or whatever else.也不是,套接字使用传输协议,但它可以是 UDP、TCP 或其他任何东西。 To clarify, you can't determine what transport protocol is being used just by saying you're using a socket;澄清一下,你不能仅仅通过说你正在使用一个套接字来确定正在使用什么传输协议。 you'd have to specify which protocol you're actually using.您必须指定您实际使用的协议。

For #1, you wouldn't need an instance to access static members of ServerMain, assuming they are accessible (eg they are public ) you can access them as ServerMain.MyVar .对于#1,您不需要实例来访问 ServerMain 的static成员,假设它们是可访问的(例如它们是public ),您可以将它们作为ServerMain.MyVar访问。

For #2, yes, you would need to look into using the synchronized statement to prevent multiple threads for writing to the list at the same time, or use a thread safe list implementation.对于#2,是的,您需要考虑使用synchronized语句来防止多个线程同时写入列表,或者使用线程安全列表实现。

For #3, the term 'sockets programming' can refer to either UDP or TCP.对于#3,术语“套接字编程”可以指 UDP 或 TCP。 Which kind of socket you use will depend on what kind of app you are implementing.您使用哪种类型的套接字将取决于您正在实现的应用程序类型。

  1. You can access as normal if you use a synchronized list (ie, Vector , one of the lists from the java.util.concurrent package, or if it's a better fit Collections.synchronizedList(list) ).如果您使用同步列表(即Vector ,java.util.concurrent package 中的列表之一,或者如果它更适合Collections.synchronizedList(list)
  2. Vector is already 'synchronized', but be aware that you have to synchronize transactions manually (ie, synchronized (vector) { vector.add(..); vector.remove(..); } ). Vector 已经“同步”,但请注意,您必须手动同步事务(即synchronized (vector) { vector.add(..); vector.remove(..); } )。 The synchronisation it employs by default essentially stops list method calls from interrupting currently-executing user-defined transactions and currently-executing method calls on the list.默认情况下,它采用的同步基本上阻止列表方法调用中断当前执行的用户定义事务和列表上当前执行的方法调用。 I'd advise using Collections.synchronizedList(list) instead of Vector , although they both do the same job, really.我建议使用Collections.synchronizedList(list)而不是Vector ,尽管它们都做同样的工作,真的。
  3. ServerSocket / Socket is TCP, DatagramSocket is UDP. ServerSocket / Socket为 TCP, DatagramSocket为 UDP。

1) That is one of the possibilities. 1)这是可能性之一。 In general, when you need to access another object methods, the best way is to keep the reference (directly or indirectly).一般来说,当您需要访问另一个 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). 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) Synchronization of access between threads is a lengthy subject and many books have been written about it. 2) 线程之间的访问同步是一个冗长的主题,已经写了很多关于它的书。 The simplest way is to use a synchronized method (or block) and do all race sensitive commands inside.最简单的方法是使用synchronized方法(或块)并在内部执行所有种族敏感命令。 But be conscient that this probably these synchronized blocks will later become your main bottleneck.但请注意,这可能这些同步块稍后将成为您的主要瓶颈。 When you have more practice, study java synchronization methods.当你有更多的练习,研究java同步方法。

3) As others java stated, you just open a socket that listens to a protocol in a given port number. 3)正如其他人 java 所说,您只需打开一个在给定端口号中侦听协议的套接字。 You can decide if you want it to be UDP or TCP.您可以决定是否希望它是 UDP 或 TCP。 Of course, keep in mind that with UDP maybe the message that you receive won't be complete, so it will have to be dealt with by your code.当然,请记住,使用 UDP 可能您收到的消息将不完整,因此必须由您的代码处理。

1) That would be a way and probably a preferred way, though not necessarily the only way. 1)这将是一种方式,并且可能是一种首选方式,尽管不一定是唯一的方式。

Also, the reference does not need to be owned by the ServerThread.此外,引用不需要由 ServerThread 拥有。 Since ServerMain is likely a singleton, I have found in situations like this that it makes sense to give that Singleton a static variable which references itself.由于 ServerMain 可能是 singleton,我发现在这种情况下,给 Singleton 一个引用自身的 static 变量是有意义的。 Then, from any ServerThread, you could do然后,从任何 ServerThread,你可以做

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

2) Yes, that will cause problems. 2)是的,这导致问题。 Read the Java Concurrency Trail , specifically the parts about synchronization.阅读Java Concurrency Trail ,特别是关于同步的部分。 This is a topic too broad to cover easily in an answer here.这是一个过于广泛的主题,无法在此处的答案中轻松涵盖。 But for a quick and dirty answer, check out synchronized methods.但要获得快速而肮脏的答案,请查看同步方法。 If you just make the method that handles this list access synchronized, then it will be safe.如果您只是使处理此列表访问的方法同步,那么它将是安全的。 Of course, depending on your needs, locking the list access might take away any performance gain from your threads.当然,根据您的需要,锁定列表访问可能会剥夺线程的任何性能提升。

3) It doesn't necessarily have to, but it generally does. 3)它不一定必须,但它通常会。 "TCP socket" is even more likely than "UDP socket", but both work. “TCP 套接字”比“UDP 套接字”更有可能,但两者都有效。 If you want a dedicated and reliable connection for an entire, prolonged transaction, you should probably use TCP.如果您想为整个长时间的交易提供专用且可靠的连接,您可能应该使用 TCP。 TCP makes guarantees that data was received and that it was received in a certain order. TCP 保证数据已被接收并按特定顺序接收。

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

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