i want to make a game with 2 players .i will use udp server and 2 clients and i dont
know how to connect 2 clients to 1 server at the same time and how they will communicate.
I will use only java.At last how the mouse click will syncronize with server
public void mousePressed(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
}
public void mouseEntered(MouseEvent event) {
}
public void mouseExited(MouseEvent event) {
}
the server
public class Provider {
public ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
String[] torino={"null","null"};
Provider() {}
void run()
{
try {
//1. creating a server socket (8080=port , 2 =number of connections)
providerSocket = new ServerSocket(8080, 2 );
//2. Wait for connection
System.out.println("Waiting for connection");
connection = providerSocket.accept();
System.out.println("Connection received from " + connection.getInetAddress().getHostName());
//3. get Input and Output streams
out = new ObjectOutputStream(connection.getOutputStream());
// flush= clean the object out
out.flush();
in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
//4. The two parts communicate via the input and output streams
try {
//take the message from client
message = (String)in.readObject();
if (torino[0]=="null")
torino[0]=message;
} else if (torino[1]=="null") {
torino[1]=message;
}
}
catch(ClassNotFoundException classnot) {
System.err.println("Data received in unknown format");
}
} catch(IOException ioException) {
ioException.printStackTrace();
}
finally {
//4: Closing connection
try {
in.close();
out.close();
providerSocket.close();
} catch(IOException ioException) {
ioException.printStackTrace();
}
}
}
//method to send messages from server to clients
void sendMessage(String msg)
{
try {
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
}
catch(IOException ioException) {
ioException.printStackTrace();
}
}
//main method
public static void main(String args[])
{
Provider server = new Provider();
while(true) {
server.run();
}
}
So now you can see in your code that you have a point where the server socket is waiting for a connection. That is the accept() method. At that point, you need to create a new Thread for handling the connection and let the main thread continue waiting for another connection. You may want to keep track of the number of connections made in a variable, say numConnections.
while(numConnections < 2){
connection = providerSocket.accept();
Thread t = new Thread(new ConnectionHandler(connection));
t.start();
numConnections++;
}
Now you ConnectionHandler class will do the work of the connection:
class ConnectionHandler implements Runnable{
Socket connection;
public ConnectionHandler(Socket connection){
this.connection = connection;
}
public void run(){
//here you do all the code associated with handling the connection
//such as your Object Streams and so on.
}
}
A quick Google search turns up many tutorials and examples of doing this such as this one. There are also some YouTude videos. You may want to start with one of those.
Related
thank you for your help.
I'm trying to stream sensor data from my android device to a server via TCP socket. I'm fairly new to Android and threads are a tough concept for me to grasp.
I have two methods, connectToServer() and sendDataToServer(). connectToServer() is called once at startup and sendDataToSever() is called over and over again at about 100 HZ. I would like to open the socket at connectToServer() and leave it open always, so that sendDataToServer() can send data on that socket repeatedly.
public static void connectToServer(){
sendThread = new Thread(new Runnable() {
public void run() {
mySocket = null;
os = null;
try {
mySocket = new Socket(PC_IP, PORT);
os = new DataOutputStream(mySocket.getOutputStream());
} catch (UnknownHostException exception) {
Log.d("sunnyDay", exception.getMessage());
} catch (IOException exception) {
Log.d("sunnyDay", exception.getMessage());
}
}
});
sendThread.start();
}
public static void sendDataToServer(byte[] data) {
String dataString = Arrays.toString(data);
// send this String to the server
sendThread = new Thread(new Runnable() {
public void run() {
if (mySocket != null && os != null) {
try {
os.writeBytes(dataString + "\n");
} catch (IOException exception) {
Log.d("sunnyDay", exception.getMessage());
}
}
}
});
sendThread.start();
}
The only way I've been able to repeatedly send data is by closing and reopening the socket every time in the same thread call, although I feel like this is not the solution.
I tried to have them both on the same thread so that the socket connection is still there, I'm assuming this is where I'm missing something about threads.
Any input is greatly appreciated.
Thanks!
os.flush() after os.writeBytes(dataString + "\n");
This is the Problem Statement i Was Given :
Design a protocol where a server is responsible to match up two chatt clients. The server listens on a TCP port for upcoming connections.
If no client is already connected to the server to be paired, the server accepts the connecting client, and makes it wait for another client. To do that, it sends a message to the connecting client to wait. When recieving this command the client constructs another Server Socket instance to listen on a port . The client then sends a mesagge to the server that contains the port number in which the newly created server listens on.
When another client, C2, seeks a connection with the server while C1 is waiting, the server informs C2 the existence of C1 by sending a message “PEER_LOC $h:$p” to C2, where $h is the host name (or IP address) of C1 and $p is the port number on which C1 is waiting. After C2 receives this message, it seeks a connection to C1 using the obtained information.Clients get the messages from users. The two clients then exchange messages until either party sends an end of stream” (Ctrl-D in Linux). Their conservation is then terminated.Sophisticated methods may employ multiple threads, timeouts, etc., and is not required in this problem.
My issues is connecting two clients to my Server. I run my server program and then two other clients classes that are duplicated of each other only with different names. I can connect to one of them only the other one just seems to wait forever.
Theses are my classes I run.
The server:
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Server {
private static ObjectOutputStream output; // stream data out
private static ObjectInputStream input; // stream data in
private static ServerSocket server;
private static Socket connection; // socket means set up connetion between 2 computers
private static int n;
//Constructor
public static void main(String[] args) throws IOException {
Server obj = new Server();
obj.RunServer();
try {
while (true) {
Handler obj2 = new Handler();
obj2.start();
System.out.println("Accepted connection from "
+ connection.getInetAddress() + " at port "
+ connection.getPort());
n++;
System.out.println("Count " + n);
}
} finally {
connection.close();
}
}
public Server() {
}
// run the server after gui created
public void RunServer() {
try {
server = new ServerSocket(6789); // 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
waitForConnection(); // wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
private void waitForConnection() {
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "WAIT ";
sendMessage(message);
do {
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("Message from Client " + message);
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
try {
output.close();
input.close();
connection.close();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush();
System.out.println("Message to client " + message);
} catch (IOException ioexception) {
}
}
public static class Handler extends Thread {
private Socket connection;
public Handler() {
String message = "WAIT";
}
public void run() {
System.out.println("Connect" + Server.connection);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForConnection() {
System.out.println("server" + server);
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
System.out.println("Connection" + connection);
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
private void whileChatting() throws IOException {
String message = " You are now connected ";
sendMessage(message);
do {
try {
message = (String) input.readObject();
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));
}
private void closeChat() {
try {
output.close();
input.close();
connection.close();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
static private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush();
} catch (IOException ioexception) {
}
}
}
}
The and one duplicated client classes C1, or C2:
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Client1 extends JFrame {
private JTextField userInput; //
private JTextArea theChatWindow; //
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private Socket connection; // socket means set up connetion between 2 computers
//Constructor
public Client1() {
}
// run the server after gui created
public void RunClient() {
try {
connection = new Socket("localhost", 6789);// 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
// wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
} finally {
closeChat();
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "";
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("message " + message);
if (message.equals("WAIT")) {
ServerSocket server2 = new ServerSocket(5000);
System.out.println("Hello");
message = "5000";
sendMessage(message);
}
System.out.println("From server " + message);
} catch (ClassNotFoundException classnotfoundException) {
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(" - " + message);
output.flush(); // send all data out
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
//
//
public static void main(String[] args) {
Client1 obj = new Client1();
obj.RunClient();
}
}
I can connect to the first Client i run the second client waits for ever.
Any Suggestions or comments would be appreciated.
You're blocking server cycle. You should start new thread for each connection from client. I would separate waitForConnection() from downstream code in server's loop in RunServer method. So your while loop there should look like:
public static void RunClient() {
...
while (true) {
try {
final Server srv = waitForConnection(); // wait for a connection between 2 computers
new Thread(new Runnable() {
public void run() {
try {
srv.setupStreams(); // set up a stream connection between 2 computers to communicate
srv.whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException ex) {
// ex.printStackTrace();
}
}
}).start();
} catch (EOFException eofException) {
}
}
In this case you have to make Server instance for each client and your server declaration should contain non-static props related to client like:
public class Server {
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private static ServerSocket server;
private Socket connection; // socket means set up connetion between 2 computers
...
And Server creation should happen inside waitForConnection() like:
private static Server waitForConnection() {
try {
Socket connection = server.accept();
return new Server(connection);
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
It's not the only way to do it. You may preserve Server class for being responsible for running main cycle in the same instance. But in this case I would create some additional class handling properties related to connection from particular client (connection, input, output).
This might help you think to bring it down to the essence, or it might not, I don't know really.
i
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server implements Runnable{
private final ServerSocket serverSocket;
private Socket clientBuffer;
public Server(int port) throws IOException {
this.serverSocket = new ServerSocket(port);
}
#Override
public void run() {
while(true) {
try {
if(clientBuffer != null) {
//Accept new connection and echo ip and port, as the assignment tells you to, then set clientBuffer to null and start the process again. Change Client accordingly.
}
} catch(Exception ex) {
System.err.println(ex.getMessage());
System.exit(1);
}
}
}
}
I'm using WiFiDirect to connect two phones and transfer images between them. I'm able to connect the devices and transfer 1 image from client to server. I'm failing when I try to transfer more than 1 image.
I use onConnectionInfoAvailable method to launch my server and client threads.
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
Log.i(TAG, "GO address " + info.groupOwnerAddress.getHostAddress() + " isGroupOwner " + info.isGroupOwner);
this.info = info;
if (info.groupFormed && info.isGroupOwner) {
ServerRunnable serverRunnable = new ServerRunnable(imageToBeSet);
Thread serverThread = new Thread(serverRunnable);
serverThread.start();
} else {
//Start client thread and transfer image.
}
ServerRunnable :
public class ServerRunnable implements Runnable {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket clientSocket = serverSocket.accept();
while (connected) {
try {
InputStream inputStream = clientSocket.getInputStream();
final byte[] result = streamToByteArray(inputStream);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
clientImage.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
//Handle exception
}
}
} catch (Exception e) {
//Handle exception
}
}
}
ClientRunnable :
public class ClientRunnable implements Runnable {
public void run() {
try {
Log.d("ClientActivity", "C: Connecting...");
Thread.sleep(2000l);
socket.bind(null);
socket.connect(new InetSocketAddress(host, PORT), 5000);
while (connected) {
if(outputStream == null) {
try {
outputStream = socket.getOutputStream();
} catch (Exception e) {
// Handle exception
}
}
}
} catch (Exception e) {
// Handle exception
}
}
public void write(byte[] bytes) {
try {
outputStream.write(bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The above write method does not work. The OutputStream is connected to the server socket when I debug I see the info about me server (ip address and post number). Not sure why the write is not being read by my server. The socket shows as connected too.
The first transfer works fine. I have a layout with Previous and Next buttons. When the button is pressed, I want to read the image byte array and transfer that. I'm unable to do this part.
If anyone knows how I can create and maintain a persistent socket connection, or any other way to transfer multiple images from client to server using WiFiDirect please let me know. I based this off of the WiFiDirectDemo in Android SDK samples.
Thanks,
Akash
P.S.: I've also looked at the WiFiP2PDemo which uses a WifiP2pDnsSdService. I'm currently trying to understand how they are keeping the sockets open for continuous chat.
Let me explain my work.
I have to send a file from server to client. In server I accepted the connection from the client and not closed the connection. Now I have to send the data as streams to the client.
Now I have selected a content and wrote in a file in method.
I have send method in which I have to send the file in inputstreams to the client. How to send?
public static void main(String args[])
{
int port=5000;
while(true)
{
try
{
ServerSocket ser=new ServerSocket(port+10);
System.out.println("CLIENT A IS CONNECTED");
ser.close();
}
catch(Exception e)
{
System.out.println(e);
}
try
{
ServerSocket ser1=new ServerSocket(port+20);
ser1.accept();
System.out.println("CLIENT B IS CONNECTED");
}
catch(Exception e)
{
System.out.println(e);
}
try
{
ServerSocket ser2=new ServerSocket(port+30);
ser2.accept();
System.out.println("CLIENT C IS CONNECTED");
}
catch(Exception e)
{
System.out.println(e);
}
try
{
ServerSocket ser3=new ServerSocket(port+40);
ser3.accept();
System.out.println("CLIENT D IS CONNECTED");
}
catch(Exception e)
{
System.out.println(e);
}
}
}
In main method I accepted All the client request.
private void jButton1ActionPerformed1(java.awt.event.ActionEvent evt) //sendbutton
{
try
{
FileReader buf=new FileReader("e:\\input.txt");
int port= // the port of client which I selected to send the data
try
{
#SuppressWarnings("resource")
ServerSocket ser=new ServerSocket(port);
Socket soc=ser.accept();
BufferedReader toclient=new BufferedReader(buf);
DataOutputStream dos=new DataOutputStream(soc.getOutputStream());
System.out.println(dos.toString());
dos.flush();
dos.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
catch(Exception e)
{
System.out.println(e);
}
}
Now my question is I already opened the ports and the connection is established in the main method. I have to send the data from server to client by selecting to which client should receive the data in sendbutton method. I am confused how to check or pass the socket object serv1 to the send method?.
below is the sample server code (please add corresponding import statements and your logic)
class SampleServer
{
private int port;
private ArrayList clientList;
public SampleServer()
{
this.port = 4444;
}
public SampleServer(int port)
{
this.port = port;
}
public void startServer()
{
ServerSocket ss = new ServerSocket(this.port);
Socket soc;
while(true)
{
soc = ss.accept();
clientList.add(soc);
}
}
public ArrayList getClientList()
{
return clientList;
}
}
Below is the sample main method (take this as a reference and create your own code)
public class Main
{
public static void main(String[] args) throws Exception
{
//Create a server
//Server has to be only one and multiple clients can connect it
SampleServer server = new SampleServer(5555);
server.startServer();
//Creating one client
Socket soc = new Socket("localhost", 5555);
//Similarly create n-number of clients and connect to the same port as that of server
//server.getClientList(); will help you get the list of the clients connected to the server
}
}
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/