i'm building a multithread example using sockets and threads in java. the sever will get multiple Socket at same time, and when i send a message from server, i want the socket from client to go back in order to what i give.
my understanding so far is to make ArrayList but i have no idea how to use it for my purpose.
can anyone help or give me any clue to solve this problem?
following is the code:
//server socket to wait before accepting from client.
public class ServerSocketEntry {
ServerSocket ssoc;
Socket soc;
ArrayList<Socket> arrSocket = new ArrayList<Socket>();
private static final int port=4853;
public ServerSocketEntry(ServerManagement sm){
try {
ssoc = new ServerSocket(port);
System.out.println("Waiting");
while(true){
soc=ssoc.accept();
arrSocket.add(soc);
System.out.println("Accepted: "+soc);
ServerSocketThread sth = new ServerSocketThread(soc,sm);
sth.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerManagement sm = new ServerManagement();
new ServerSocketEntry(sm);
}
}
//threadClass using readObject(), writeObject() method.
public class ServerSocketThread extends Thread {
Socket soc;
ObjectOutputStream oos;
ObjectInputStream ois;
ServerManagement sm;
Food food;
public ServerSocketThread(Socket soc,ServerManagement sm) {
this.soc=soc;
this.sm=sm;
try {
ois= new ObjectInputStream(soc.getInputStream());
oos= new ObjectOutputStream(soc.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void run(){
Command com;
while(true){
try {
com = (Command) ois.readObject();
if(com.getCommand()==Command.Member_Check){
Member member = (Member) com.getObj();
System.out.println("thread: "+member);
if(sm.checkMember(member)){
com.setCommand(Command.Command_OK);
}else{
com.setCommand(Command.Command_Fail);
}
}else if(com.getCommand()==Command.LogIn_Check){
Member member = (Member) com.getObj();
if(sm.checkLogIn(member)){
com.setCommand(Command.Command_OK);
}else{
com.setCommand(Command.Command_Fail);
}
}else if(com.getCommand()==Command.Food_Check){
ArrayList<Food> serverArrFood = com.getFoodOrder();
if(sm.checkFood(serverArrFood)){
com.setCommand(Command.Command_OK);
}else{
com.setCommand(Command.Command_Fail);
}
}
oos.writeObject(com);
oos.flush();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Then you may use a hash map to store the connected clients and it will be easy to get a specific client from the map and send message to that. Use a nickname of the client as the key and socket as a value at the time when a new client connects to the sever. Put these values into the map. For Example:
Map<String, Socket> clients = new HashMap();
clients.put(nickname, clientSocket);
While writing simply get that specific client by its key.
clients.get(nickname);
and write to its output stream. When one client sends message to a specific client, it should send the receiver's nickname as part of the message to the server.
Related
I want to integrate a server with multiple clients for a blackjack game I created, and thus I began practicing with servers in java. I create a thread, that when ran, forces the server to listen for input and produce an output. Then I added a feature to stop the server. However, the server randomly produces the correct output, and sometimes fails to connect. Here is the code for when the user hosts a server:
st = new ServerThread(); //this is a field of type ServerThread
st.start(); //this runs the server concurrently as a new thread
Here is the code for when they close a server:
st.stopThread();
Finally, here is the source for the serverThread:
public class ServerThread extends Thread {
private volatile boolean isRunning = true;
private Socket socket;
private static final int PORTNUM = 1342;
#Override
public void run() {
while (isRunning) { //should run only when the
try {
ServerSocket serverSocket = new ServerSocket(PORTNUM); //uses the same port number, which I made a constant
//Reading the an object of type Information from the client
socket = serverSocket.accept();
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
Information i = (Information) serverInputStream.readObject();
//arbitrarily changes the data stored in the information object to verify connection with server
i.setI(100);
i.setS("new string");
i.setD(4.4);
//sends the modified object back to the client
serverOutputStream.writeObject(i);
serverInputStream.close();
serverOutputStream.close();
socket.close();
} catch (IOException e) {
//System.out.println("IOException");
//e.printStackTrace();
} catch (ClassNotFoundException e) {
//System.out.println("ClassNotFoundException");
//e.printStackTrace();
} finally {
try {
if (socket != null) { //avoid null pointer if no connections have been established
socket.close();
}
} catch (IOException ex) {
//Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
Any suggestions on edits to make my code perform correctly and consistently would be welcome. Thanks.
I would move the socket definition away from being an instance variable i.e,
while (isRunning) {
Socket socket = null;
try {
...
I am programming a external Taskmanager and i need to send the process list via tcp to my server application. But i don't know how to start and how this works.
Edit:
I have the processlist i only have to send it via TCP to the Serverside.
Thx for your help.
If you already have a processlist, then it's not so hard to make client-server logic for your purposes with Java. First of all, you need to make a server side:
public class ServerSide {
public static void main(String[] args) {
try
{
ServerSocket myServerSocket = new ServerSocket(9999);
Socket skt = myServerSocket.accept();
List<Process> objects = null;
try {
ObjectInputStream objectInput = new ObjectInputStream(skt.getInputStream());
try {
Object object = objectInput.readObject();
objects = (ArrayList<Process>) object;
System.out.println(objects);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Wich will use a ServerSocket to listen on specified port, in this case is 9999. Then connection accepted (take a look at myServerSocket.accept(), it stops the execution, until any connection is accepted), it creates a Socket and you can get it's InputStream and get an object from it. In this example server stops after first accepted connection, you should make it accept any number of connections with infinity loop for example.
When you have a server, you can make a client side, which will send a list of Processes to the Server:
public class ClientSide {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",9999);
ArrayList<Process> my = new ArrayList<Process>();
my.add(new Process("Test1"));
my.add(new Process("Test2"));
try
{
ObjectOutputStream objectOutput = new ObjectOutputStream(socket.getOutputStream());
objectOutput.writeObject(my);
}
catch (IOException e)
{
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In this case, you'll create a Socket by youself, give an eddress and port number to it, where it will send a data. Then you can get an OutputStream and pass your data through it. In example above, you pass an Array of Process object instances. The Process class looks like:
public class Process implements Serializable {
private String processName = null;
public Process(String processName) {
this.processName = processName;
}
#Override
public String toString() {
return processName;
}
}
The main thing in case of Process class, it should implement the Serializable interface. In that case, you don't need to make some logic for it's serialization.
But if you have to make a client with Java, but not a server, then it could be a little bit harder. You may take a look here, to see some kind of example, how Java-client communicates with C++ server. Anyway, in Java-part you should use a Socket and it's OutputStream, only the data representation will differ.
I have a ArrayList<Socket> listOfSockets that adds a socket when I receive clientsocket = serversocket.accept() like this listOfSockets.add(clientsocket)
and then I send this whole list to another class like this.
Server_Client client = new Server_Client(clientSock, clientSocketList);
Thread X = new Thread(client);
X.start();
Here is the code for my class that I send the list and socket to
public class Server_Client implements Runnable{
//ArrayList<String> UserNameList;
ArrayList<Socket> clientSocketList;
Socket socket = null;
public Server_Client(Socket X, ArrayList<Socket> L){
this.socket = X;
this.clientSocketList = L;
}
#Override
public void run() {
try {
ListenforMessage NewMessages = new ListenforMessage(socket);
Thread myThread = new Thread(NewMessages);
myThread.start();
} catch (Exception e) {
System.err.println(e);
}
}
//------------------------------------------------------------------
//Class that handles incoming messages!
class ListenforMessage implements Runnable{
Socket socket;
DataInputStream IN;
DataOutputStream OUT;
public ListenforMessage(Socket x) {
this.socket = x;
}
#Override
public void run() {
try {
while (true) {
IN = new DataInputStream(socket.getInputStream());
OUT = new DataOutputStream(socket.getOutputStream());
String message = IN.readUTF();
//System.out.println(message);
for (Socket TEMP_SOCK : clientSocketList) {
if(TEMP_SOCK != this.socket){
SendMessage(message);
}
}
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void SendMessage(String m) throws IOException{
try {
DataOutputStream OUT = new DataOutputStream(socket.getOutputStream());
OUT.writeUTF(m);
System.out.println("User said: " + m);
} catch (Exception e) {
}
}
//------------------------------------------------------------------
}
In the ListenforMessage class, in the for-loop I go trough the size of list and if TEMP_SOCK is not this.socket then I want to send a message to that socket, and if it is then don't do anything. But my problem is that when I connect with 2 clients they can't send message to each other. They just send the message to the server and the server sends back the message to the client. My question is, can you use a list like I do to check if the socket is not the socket that you are YOURSELF.
cause now Client1 sends a messages and receive the same messages from sever, and Client2 does the same thing.
I want Client1 to send and Client2 to receive the message(And other sockets on the same list)
Your code doesn't work because you should let SendMessage know to which socket it should send the message (i.e. you should pass TEMP_SOCK to it), instead, you're making it use the socket variable, which is the socket connected to the client that just sent the message.
I'm a a beginner programmer, currently stuck on a java project. I have a fully working singleplayer minesweeper game, object-oriented, and I'm trying to implement a TCP multiplayer function. The game has a control class, which handles the view, game field, timer, labels, has the action listeners, etc.
For multiplayer, I'm trying to make a separate thread, which has the Socker and the ServerSocket, and depending on the parameters passed on by the constructor, acts as a host or client. While running, it should be trying to read my custom Packet class from the input stream, and another method can send packets. Here is the code:
public class MultiThread extends Thread {
GameControl gc;
ServerSocket servSocket;
Socket socket;
Packet data;
ObjectInputStream incoming;
ObjectOutputStream outgoing;
Boolean isHost;
Boolean commEnd;
public MultiThread(GameControl gc, Boolean isHost) {
this.gc = gc;
this.isHost = isHost;
this.commEnd = false;
gc.chatDialog.setVisible(true);
}
public void run() {
try {
if (isHost) {
servSocket = new ServerSocket(1234);
gc.chatDialog.status.setText("Awaiting connection...");
socket = servSocket.accept();
gc.chatDialog.status.setText("Connected.");
incoming = new ObjectInputStream(socket.getInputStream());
outgoing = new ObjectOutputStream(socket.getOutputStream());
}
else if (!isHost){
socket = new Socket("localhost", 1234);
if (socket.isConnected()) {
gc.chatDialog.status.setText("Connected.");
incoming = new ObjectInputStream(socket.getInputStream());
outgoing = new ObjectOutputStream(socket.getOutputStream());
}
else {
gc.chatDialog.status.setText("No connection.");
}
}
while (!commEnd) {
try {
Thread.sleep(100);
data = (Packet)incoming.readObject();
System.out.println(data.msg);
gc.chatDialog.chatArea.append(data.getMsg());
}
catch (IOException e) {e.printStackTrace();}
}
System.out.println("asd");
gc.chatDialog.status.setText("No connection");
incoming.close();
outgoing.close();
socket.close();
servSocket.close();
}
catch (Exception e) {e.printStackTrace();}
}
public void sendPacket(Packet p) {
try {
outgoing.writeObject(p);
}
catch (IOException e) {e.printStackTrace();}
}
}
The connection gets established on localhost, but I'm getting an exception thrown when trying to initialize the incoming and outgoing fields.
Sorry if the code is a mess, I get the feeling I'm in some serious misunderstanding, so any help is appreciated.
So now, I am making a client server app based multithread. In server side, I make a thread for everysingle connection that accepted.
In thread class, I make a method that send a command to client. What i just want is, how to send a parameter to all running client? For simple statement, i just want to make this server send a message to all connected client.
I've been read this post and find sendToAll(String message) method from this link. But when i am try in my code, there is no method like that in ServerSocket .
Okay this is my sample code for server and the thread.
class ServerOne{
ServerSocket server = null;
...
ServerOne(int port){
System.out.println("Starting server on port "+port);
try{
server = new ServerSocket(port);
System.out.println("Server started successfully and now waiting for client");
} catch (IOException e) {
System.out.println("Could not listen on port "+port);
System.exit(-1);
}
}
public void listenSocket(){
while(true){
ClientWorker w;
try{
w = new ClientWorker(server.accept());
Thread t = new Thread(w);
t.start();
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
}
}
protected void finalize(){
try{
server.close();
} catch (IOException e) {
System.out.println("Could not close socket");
System.exit(-1);
}
}
}
class ClientWorker implements Runnable{
Socket client;
ClientWorker(Socket client){
this.client = client;
}
public void run(){
...
sendCommand(parameter);
...
}
public void sendCommand(String command){
PrintWriter out = null;
try {
out = new PrintWriter(client.getOutputStream(), true);
out.println(command);
} catch (IOException ex) {}
}
}
Thanks for help :)
The below answer, is not recommended for a full fledged server, as for this you should use Java EE with servlets, web services etc.
This is only intended where a few computers want to connect to perform a specific task, and using simple Java sockets is not a general problem. Think of distributed computing or multi-player gaming.
EDIT: I've - since first post - greatly updated this architecture, now tested and thread-safe. Anybody who needs it may download it here.
Simply use (directly, or by subclassing) Server and Client, start() them, and everything is ready. Read the inline comments for more powerful options.
While communication between clients are fairly complicated, I'll try to simplify it, the most possible.
Here are the points, in the server:
Keeping a list of connected clients.
Defining a thread, for server input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Some utility methods for sending messages.
And for the client:
Defining a thread, for client input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Here's the Server class:
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);
}
}
And here for the Client class:
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);
}
}
There is no method in server socket to send data or message to all running clinet threads.
Please go through the ServerThread.java program which is calling the sendToAll usng server.
// ... and have the server send it to all clients
server.sendToAll( message );
Check out zeroMQ. There are methods known as "pub sub" or "publish subscribe" that will do what you want. You can also use it to communicate between your threads. It is an amazing library in my opinion. It has java or jzmq bindings along with over 30+ others as well so you should be able to use it in your program.
http://www.zeromq.org/