Witam.
Chciałem poćwiczyć sobie tworzenie połączeń sieciowych w planach mam napisanie prostej gierki ale chciałem zacząć od czegoś prostego stanęło na chacie.
Przede wszystkim chciałem osiągnąć coś takiego, server tworzy pule połączeń (jedno przypada dla jednego klienta) gdy klient łączy się z serverem to to połączenie jest trzymane tak aby klient gdy chce coś wysłać do servera nie musiał tworzyć nowego połączenia.
Niestety ale mam z tym problem i obecnie w klasie "Sender" aby wysłać coś na server muszę tworzyć nowe połączenie a następnie go zamykać inaczej wiadomość nie jest wysyłana. Raczej nie muszę pisać, że przez to pula połączeń szybko się wyczerpuje. Bardzo uproszczając to to co chcę osiągnąć to aby po naciśnięciu przycisku "Send" wiadomość była wysyłana na serwer przy użyciu tego samego połączenia.
Mam nadzieję, że nie zamotałem zapewne jest to banalny problem ale jakoś nie mogę sobie z tym poradzić poniżej zamieszczam kod klienta i servera (server raczej jest w porządku):
Klasa "Sender" ta z którą mam problem i wymaga przebudowy

package com.connector;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Sender {

	public Sender(){
	}
	
	public static void send(String data) {
		Socket clientSocket = null;
		try {
			clientSocket = new Socket("localhost", 6789);
			DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
			outToServer.writeBytes(data);
			clientSocket.close();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
 

Klasa odbierająca wiadomość

 package com.connector;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

import com.client.ClientFrame;

public class Recipient extends Thread {
	private String dataFromServer;
	private Socket clientSocket;
	private BufferedReader inpStrFromServer;
	
	public Recipient(Socket clientSocket){
		this.clientSocket = clientSocket;
	}
		
	public void run(){
		try {
			while(true){
				inpStrFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
				dataFromServer = inpStrFromServer.readLine();
				ClientFrame.getInstance().getTxtaField().append(dataFromServer+"\n");
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Tu w planach mam zamiar spiąć do kupy istotne zmienne dla klas "Recipient " i "Sender"

package com.connector;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Connector {

	private Socket clientSocket;
	
	public Connector(){
		init();
	}
	
	private void init(){
		try {
			clientSocket = new Socket("localhost", 6789);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		new Thread(new Recipient(clientSocket)).start();
	}
} 

Klasy servera

package com.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	
	private Socket socket;
	private ServerSocket serverSocket;
	private ServerClient[] clients = new ServerClient[10];
	
	public static void main(String argv[]){
		try {
			new Server().init();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void init() throws IOException{
		serverSocket = new ServerSocket(6789);
		
		while (true) {
			socket = serverSocket.accept();
			for(int i = 0; i<9;i++){
				if(clients[i] == null) {
					(clients[i] = new ServerClient(i, socket, clients)).start();
					break;
				}
			}
		}
	}
}
 
package com.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class ServerClient extends Thread {
	
	private int id;
	
	// Odczytuje dane klienta.
	private BufferedReader is = null;
	// Wysyła dane do klienta
	private PrintStream os = null;
	
	private Socket socket;
	private ServerClient[] clients = new ServerClient[10];
	
	public ServerClient(int id, Socket socket, ServerClient[] cliens){
		this.id = id;
		this.socket = socket;
		this.clients = cliens;
	}
	
	public void run() {
		String insData;
		try {
			is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			os = new PrintStream(socket.getOutputStream());
			
			insData = is.readLine();
			System.out.println("User id["+id+"] message "+insData );
			
			// Rozsyłam informację do wszystkich użytkowników.
			for (int i = 0; i <= 9; i++) {
				if (clients[i] != this) { // Wiadomość nie jest wysyłana do wysyłającego.
					if (clients[i] != null){
						//log.info(line);
						clients[i].os.println(insData +" - server");
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
 

Klasy dodatkowe (okienko)

 package com.client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.connector.Sender;

public class ClientFrame extends JFrame implements KeyListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 9131704331147990382L;
	
	private static ClientFrame frame = null;
	private JPanel pnlMain = new JPanel(new BorderLayout());
	private JTextField txtField = new JTextField();
	private JTextArea txtaField = new JTextArea();
	private JButton btnSend = new JButton();
	
	public static ClientFrame getInstance(){
		if(frame == null) {
			frame = new ClientFrame();
		}
		return frame;
	}
	
	private ClientFrame(){
		init();
	}
	
	private void init(){
		this.setSize(new Dimension(300, 200));
		this.getContentPane().add(getCommponents());
		this.setVisible(true);
		this.setResizable(false);
		this.setLocation(400, 400);
		
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}
	
	private JPanel getCommponents(){
		JPanel pnlTop = new JPanel(new BorderLayout());
		pnlTop.setBackground(Color.GRAY);
		pnlTop.setPreferredSize(new Dimension(150, 5));
		
		JPanel pnlCenter = new JPanel(new BorderLayout());
		pnlCenter.setPreferredSize(new Dimension(150, 60));
		txtaField.setPreferredSize(new Dimension(170, 60));
		pnlCenter.add(txtaField, BorderLayout.CENTER);

		JPanel pnlBottom = new JPanel(new BorderLayout());
		pnlBottom.setBackground(Color.LIGHT_GRAY);
		pnlBottom.setPreferredSize(new Dimension(150, 25));
		txtField.setPreferredSize(new Dimension(190, 25));
		pnlBottom.add(txtField, BorderLayout.WEST);
		pnlBottom.add(getButtonSend(), BorderLayout.EAST);
		
		pnlMain.add(pnlTop, BorderLayout.NORTH);
		pnlMain.add(pnlCenter, BorderLayout.CENTER);
		pnlMain.add(pnlBottom, BorderLayout.SOUTH);
		
		return pnlMain;
	}
	
	private JButton getButtonSend(){
		btnSend.setPreferredSize(new Dimension(100, 25));
		btnSend.setText("Send");
		btnSend.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				Sender.send(txtField.getText());
			}
		});
		return btnSend;
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		
	}

	public JTextArea getTxtaField() {
		return txtaField;
	}

}

Klasa uruchamiająca aplikację

 package com.client;

import com.connector.Connector;

public class Client {
	
	public static void main(String argv[]) throws Exception {
		ClientFrame.getInstance();
		new Connector();
	}
}