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
.
My questions are simple:
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开发者_如何学JAVA I've already "left" the area of the ServerMain while being in the specific thread which runs in the background. Is the only way is to hold a reference from each serverthread to papa ServerMain?
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?
General question: does sockets programming means UDP or TCP?
I'd like to hear some good advice. Thanks in advance.
For #1, you wouldn't need an instance to access static members of ServerMain, assuming they are accessible (e.g. they are public
) you can access them as 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.
For #3, the term 'sockets programming' can refer to either UDP or TCP. Which kind of socket you use will depend on what kind of app you are implementing.
1) That is one of the possibilities. In general, when you need to access another object methods, the best way is to keep the reference (directly or indirectly). 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. The simplest way is to use a synchronized
method (or block) and do all race sensitive commands inside. But be conscient that this probably these synchronized blocks will later become your main bottleneck. When you have more practice, study java synchronization methods.
3) As others java stated, you just open a socket that listens to a protocol in a given port number. You can decide if you want it to be UDP or 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.
- 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. Now, you may need to synchronize access to it, but I don't really see that as changing how you reference things.
- Synchronize the list (preferably use the java.util.concurrent package). Make sure that the Tables themselves are thread-safe as well.
- Neither, a socket uses a transport protocol, but it could be UDP, TCP, or whatever else. 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.
- You can access as normal if you use a synchronized list (i.e.,
Vector
, one of the lists from the java.util.concurrent package, or if it's a better fitCollections.synchronizedList(list)
). - Vector is already 'synchronized', but be aware that you have to synchronize transactions manually (i.e.,
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 usingCollections.synchronizedList(list)
instead ofVector
, although they both do the same job, really. ServerSocket
/Socket
is TCP,DatagramSocket
is UDP.
1) That would be a way and probably a preferred way, though not necessarily the only way.
Also, the reference does not need to be owned by the 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. Then, from any ServerThread, you could do
class ServerThread extends Thread
{
public void someMethod()
{
ServerMain.serverMain.whatever();
}
}
2) Yes, that will cause problems. Read the Java Concurrency Trail, specifically the parts about synchronization. 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. "TCP socket" is even more likely than "UDP socket", but both work. If you want a dedicated and reliable connection for an entire, prolonged transaction, you should probably use TCP. TCP makes guarantees that data was received and that it was received in a certain order.
精彩评论