以下の回答は、本格的なサーバーにはお勧めできません。これについては、サーブレット、Web サービスなどで Java EE を使用する必要があります。
これは、少数のコンピューターが特定のタスクを実行するために接続したい場合にのみ意図されており、単純な Java ソケットを使用することは一般的な問題ではありません。分散コンピューティングやマルチプレイヤー ゲームを考えてみてください。
編集:私は-最初の投稿以来-このアーキテクチャを大幅に更新し、テスト済みでスレッドセーフになりました。必要な人は、ここからダウンロードできます。
(直接、またはサブクラス化して)Server
とClient
を使用するだけstart()
で、すべての準備が整います。より強力なオプションについては、インライン コメントを参照してください。
クライアント間の通信はかなり複雑ですが、できるだけ単純化するようにします。
サーバー内のポイントは次のとおりです。
- 接続されたクライアントのリストを保持します。
- サーバー入力用のスレッドの定義。
- 受信メッセージのキューを定義します。
- キューからスレッドをポーリングし、それを操作します。
- メッセージを送信するためのいくつかのユーティリティ メソッド。
クライアントの場合:
- クライアント入力用のスレッドを定義します。
- 受信メッセージのキューを定義します。
- キューからスレッドをポーリングし、それを操作します。
サーバークラスは次のとおりです。
public class Server {
private ArrayList<ConnectionToClient> clientList;
private LinkedBlockingQueue<Object> messages;
private ServerSocket serverSocket;
public Server(int port) {
clientList = new ArrayList<ConnectionToClient>();
messages = new LinkedBlockingQueue<Object>();
serverSocket = new ServerSocket(port);
Thread accept = new Thread() {
public void run(){
while(true){
try{
Socket s = serverSocket.accept();
clientList.add(new ConnectionToClient(s));
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
accept.setDaemon(true);
accept.start();
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToClient {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToClient(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true); // terminate when main ends
read.start();
}
public void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void sendToOne(int index, Object message)throws IndexOutOfBoundsException {
clientList.get(index).write(message);
}
public void sendToAll(Object message){
for(ConnectionToClient client : clientList)
client.write(message);
}
}
Client クラスについては、次のとおりです。
public class Client {
private ConnectionToServer server;
private LinkedBlockingQueue<Object> messages;
private Socket socket;
public Client(String IPAddress, int port) throws IOException{
socket = new Socket(IPAddress, port);
messages = new LinkedBlokingQueue<Object>();
server = new ConnecionToServer(socket);
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToServer {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToServer(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true);
read.start();
}
private void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void send(Object obj) {
server.write(obj);
}
}