TCP Sockets Client/Server - server only respondsto first connection from client - java

I have some simple client and server code, where the client sends some bytes to the server, and the server responds with some bytes. The client prints the received bytes, and then closes the socket.
This works fine the first time the client runs, but subsequent calls get no response.
package sockets.com;
// Client Side
import java.io.*;
import java.net.*;
public class ClientSideTCPSocket {
public void run() {
try {
int serverPort = 4023;
InetAddress host = InetAddress.getByName("localhost");
System.out.println("Connecting to server on port " + serverPort);
Socket socket = new Socket(host, serverPort);
System.out.println("Just connected to " + socket.getRemoteSocketAddress());
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
String s = "HELLO SERVER";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
out.write(b);
}
int ch = 0;
while ((ch = in.read()) >= 0) {
System.out.println("Got byte " + ch);
}
out.flush();
out.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ClientSideTCPSocket client = new ClientSideTCPSocket();
client.run();
}
}
Server code
package sockets.com;
//Server Side
import java.net.*;
import java.io.*;
public class ServerSideTCPSocket {
public void run() {
try {
int serverPort = 4023;
ServerSocket serverSocket = new ServerSocket(serverPort);
serverSocket.setSoTimeout(900000);
while (true) {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
//
int ch = 0;
while ((ch = server.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
}
// Write to output stream
OutputStream out = server.getOutputStream();
String s = "HELLO CLIENT";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
System.out.println(b);
out.write(b);
}
}
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerSideTCPSocket srv = new ServerSideTCPSocket();
srv.run();
}
}
Would be grateful for any comments regarding why this is the case. Thank you.

A few things:
This block of code will loop forever until after the client closes his connection:
while ((ch = server.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
}
Then after the client closes his connection, the subsequent attempt to send "HELLO CLIENT" to the socket will generate an IO exception. That will trigger your server loop to exit.
The easy fix is to adjust your protocol such that the "message" is completed on some sentinel char. In my easy fix, I just adjusted it to break out when a ! was received.
Better to have each client session terminate on an ioexception instead of the entire server block. My refactor of your code:
public class ServerSideTCPSocket {
public void tryCloseSocketConnection(Socket socket) {
try {
socket.close();
}
catch(java.io.IOException ex) {
}
}
public void processClientConnection (Socket clientConnection) throws java.io.IOException {
int ch = 0;
while ((ch = clientConnection.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
if (ch == '!') {
break;
}
}
// Write to output stream
OutputStream out = clientConnection.getOutputStream();
String s = "HELLO CLIENT!";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
System.out.println(b);
out.write(b);
}
}
public void run() {
try {
int serverPort = 4023;
ServerSocket serverSocket = new ServerSocket(serverPort);
serverSocket.setSoTimeout(900000);
while (true) {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket clientConnection = serverSocket.accept();
try {
System.out.println("Just connected to " + clientConnection.getRemoteSocketAddress());
processClientConnection(clientConnection);
}
catch (java.io.IOException ex) {
System.out.println("Socket connection error - terminating connection");
}
finally {
tryCloseSocketConnection(clientConnection);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerSideTCPSocket srv = new ServerSideTCPSocket();
srv.run();
}
}
Then adjust your client code's message to be:
String s = "HELLO SERVER!"; // the exclamation point indicates "end of message".

Related

why is this Java Proxy Server very slow?

I need a Java Proxy Server that let me connect to [localhost:9318] through [localhost:9418], like:
[my browser] -> [localhost:9418] -> [localhost:9318]
for that I tried this code:
http://www.java2s.com/Code/Java/Network-Protocol/Asimpleproxyserver.htm
package com.example.proxyserver;
import java.io.*;
import java.net.*;
public class App {
public static void main(String[] args) throws IOException {
try {
String host = "localhost";
int remoteport = 9318;
int localport = 9418;
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport);
// And start running the server
runServer(host, remoteport, localport); // never returns
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on the specified local port. It never
* returns.
*/
public static void runServer(String host, int remoteport, int localport) throws IOException {
// Create a ServerSocket to listen for connections with
ServerSocket ss = new ServerSocket(localport);
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n");
out.flush();
client.close();
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
}
catch (IOException e) {
}
}
}
}
}
This code works but it is very slow.
Do you know what do I need to do in order to increase the speed?
Or maybe do you know about another Java Proxy Server code that be fast?
Thanks!

Why is my message sent only once in Java socket server?

there is a server that is considered to server multiple clients at the same time.
So when clients connects, he is added to clients array. And when server gets the message, it is sent to all the clients.
It works perfectly when one client is connected, but when I have 2 clients at the same time, the message is sent only once, it doesn't work anymore after that. What's the problem?
Server
static DataInputStream inputStream;
static DataOutputStream outputStream;
static ServerSocket serverSocket;
static final int PORT = 3003;
static Socket someClient;
static List<Socket> clients = new ArrayList<>();
public Server()
{
start();
}
public static void main(String[] args) throws IOException
{
try{
serverSocket = new ServerSocket(PORT);
print("Server started on " + serverSocket.getInetAddress().getHostAddress());
while (true)
{
someClient = serverSocket.accept();
new Server();
}
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void run()
{
try{
clients.add(someClient);
print("Connected from " + someClient.getInetAddress().getHostAddress());
InputStream sin = someClient.getInputStream();
OutputStream sout = someClient.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
String message;
while (true)
{
message = inputStream.readUTF();
print(message);
for (int i = 0; i < clients.size(); i++)
{
Socket client = clients.get(i);
OutputStream os = client.getOutputStream();
DataOutputStream oss = new DataOutputStream(os);
oss.writeUTF(message);
}
}
} catch (Exception e){
e.printStackTrace();
}
}
Client
socket = new Socket("0.0.0.0", 3003);
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(key != null && key.length() == 16)
{
Date date = new Date();
String msg = ">> " + nickname + ": " + messageField.getText()+" | " + date.getHours()+":"+date.getMinutes()+"\n";
try {
outputStream.writeUTF(Encrypt.AESEncrypt(key, msg));
} catch (IOException e1) {
e1.printStackTrace();
}
messageField.setText("");
}
else if(key == null)
JOptionPane.showMessageDialog(J_Frame, "Your key field is empty");
else if(key.length() != 16)
JOptionPane.showMessageDialog(J_Frame, "Key's length should be 16 symbols");
}
});
while (true)
{
String message;
message = inputStream.readUTF();
append("\n" + Encrypt.AESDecrypt(key, message));
}
} catch (Exception e1) {
clear();
append(">> Unable to connect to the server.");
hideButtons();
}
Every time a client connects to your server, it replaces the previous connection:
while (true)
{
someClient = serverSocket.accept();
...
}
someClient is static:
static Socket someClient;
which means it is shared by all threads.
Also, access to it is not synchronized in any way, which means changes to its value are not guaranteed to be visible to other threads.
As Peter Lawrey pointed out in the comments, the streams also need to be non-static:
static DataInputStream inputStream;
static DataOutputStream outputStream;
actually, the fact that you are always reading from the "latest" inputStream may be the main cause of the behavior you are describing.
outputStream seems to be unused, so it might be best to remove it.
In addition to that, OutputStreams may need to be flushed in order to actually send data.

Maximum socket connections available

I am trying my hand at socket programming. I built a simple echo server that prints the client text on the screen and sends back a thank you message to the client. However when I run the client (which individually spawns 10000 requests in a loop) sometimes i get "connection refused" exceptions in some client threads. Sometimes all go through without any exception.
Following is my server code :
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Following is my client code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Not sure what I might be doing wrong. Any suggestions ?
You're expecting too much. It just isn't realistic for a client to form 10,000 connections at maximum speed. You're forgetting about the TIME_WAIT state, and the fact that there are only 64k minus several dozen client-side ports available. It isn't a realistic test. If you want to load-test your server you will need quite a few client hosts, or a longer interval between connections.

Server alternates between users instead of broadcasting

I have been working on a message system where users type in a server IP/Port and that server then takes in messages and relays them to all other users on the server. The whole program was based of a echo server i rewrote from scratch, for every server.accept() socket it creates two Threads, one to receive messages and one to send them back. The two Threads are connected by a DatagramPacket system so if the server receives a message from one socket it sends it back to all other users because their Threads are listening for the same thing, this is where i am encountering problems; everything work fine except the fact that the user who receives the message alternates in order to time of log on.
Example of problem when two clients are connected:
Client #1 sends 10 messages:
0
1
2
3
4
5
6
7
8
9
The Server receives all of them.
Client #1 receives:
1
3
5
7
9
Client #2 receives:
0
2
4
6
8
Here is the code for the Client:
import java.io.*;
import java.util.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MessageClient {
public static void main(String[] args) {
System.out.println("Starting Message System...");
Scanner in = new Scanner(System.in);
MessageClient mc = new MessageClient();
String input;
System.out.println(":System Started, type help for help.");
System.out.print(":");
while (true) {
input = in.nextLine();
if (input.equalsIgnoreCase("HELP")) {
mc.printHelp();
System.out.print(":");
} else if (input.equalsIgnoreCase("QUIT")) {
System.exit(0);
} else if (input.equalsIgnoreCase("CONNECT")) {
mc.connect(in);
in.nextLine();
System.out.print(":");
} else {
System.out.print("No command found.\n:");
}
}
}
public static void printHelp() {
System.out.println("help\tShow this prompt\nconnect\tStarts a new connection\nquit\tQuit the program\nexit\tExit a connection");
}
public void connect(Scanner in) {
Socket soc = null;
InetAddress addr = null;
System.out.print("IP_ADDRESS/HOST:");
String ip = in.nextLine();
System.out.print("PORT:");
int port = in.nextInt();
try {
System.out.println("Attempting to connect to HOST:\'" + ip + "\' on PORT:\'" + port + "\'");
addr = InetAddress.getByName(ip);
soc = new Socket(addr, port);
} catch(Exception e) {
System.out.println("Error connecting to server: " + e.getLocalizedMessage());
return;
}
SwingUtilities.invokeLater(new MessageGUI(ip + ":" + port, soc));
}
}
class MessageGUI implements Runnable {
public MessageGUI(String windowName, Socket server) {
JFrame window = new JFrame(windowName);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setSize(500, 300);
window.setLayout(new BorderLayout());
window.setVisible(true);
MessageReceive mr = new MessageReceive(server);
mr.setEditable(false);
mr.setBackground(new Color(0, 0, 0));
mr.setForeground(new Color(0, 255, 0));
mr.setVisible(true);
new Thread(mr).start();
window.add(mr, BorderLayout.CENTER);
DataOutputStream dos = null;
try {
dos = new DataOutputStream(server.getOutputStream());
} catch(Exception e) {
System.out.println("Error creating output stream to server: " + e.getLocalizedMessage());
}
JTextField input = new JTextField();
input.addActionListener(new MessageSend(server, input, dos));
input.setBackground(new Color(0, 0, 0));
input.setForeground(new Color(0, 255, 0));
window.add(input, BorderLayout.PAGE_END);
System.out.println("Displaying connection.");
}
public void run() {}
}
class MessageReceive extends JTextArea implements Runnable {
protected Socket server;
public MessageReceive(Socket server) {
this.server = server;
}
public void run() {
DataInputStream dis = null;
int bytes;
try {
dis = new DataInputStream(server.getInputStream());
} catch(Exception e) {
System.out.println("Error connecting server: " + e.getLocalizedMessage());
}
this.append("Connected.\n");
while (true) {
try {
while ((bytes = dis.read()) != -1) this.append(String.valueOf((char) bytes));
} catch(Exception e) {
System.out.println("Error reading from server: " + e.getLocalizedMessage());
return;
}
}
}
}
class MessageSend implements ActionListener {
protected Socket server;
protected JTextField input;
protected DataOutputStream dos = null;
public MessageSend(Socket server, JTextField input, DataOutputStream dos) {
this.server = server;
this.input = input;
this.dos = dos;
}
public void actionPerformed(ActionEvent ae) {
try {
dos.writeBytes(input.getText() + "\n");
input.setText("");
} catch(Exception e) {
System.out.println("Error writing to server output stream: " + e.getLocalizedMessage());
}
}
}
Here is the code for the Server:
import java.io.*;
import java.net.*;
import java.util.*;
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer ms = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
DatagramSocket ds = null;
try {
ds = new DatagramSocket(4);
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ds).start();
new MessageConnectionOut(client, ds).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionOut(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ds.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionIn(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ds.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
UPDATE:
I tried replacing all the DatagramSockets with MulticastSockets and adding it to a group when I declared it, MessageServer.main(). The same problem occurred.
Multicast code:
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer msgsrv = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
MulticastSocket ms = null;
try {
ms = new MulticastSocket(4);
ms.joinGroup(InetAddress.getByName("225.65.65.65"));
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ms).start();
new MessageConnectionOut(client, ms).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionOut(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ms.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
System.out.println("SENT_TO:" + this.getName());
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionIn(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ms.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
This sample may be help you out.
There is 2 threads for Server.
One for reading UDP messages. I used 2 different ports since I just want to avoid messages read by same process. I don't have 2 machines to test it. Tested on my local host.
Another thread will broadcast UDP messages received by reader thread.
There is a thread safe list which acts between threads as data sync. Received data added to the list. Broadcaster thread polling the list for the data, if there is any broadcast and else sleep for 500 microseconds. Threads are created using executor.
private final static String INET_ADDR = "224.0.0.3";
private final static int PORT1 = 8888;
private final static int PORT2 = 8889;
private static List<String> threadSafeList = null;
public static void main(String[] args) throws UnknownHostException, InterruptedException {
threadSafeList = new CopyOnWriteArrayList<String>();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Sender(InetAddress.getByName(INET_ADDR), PORT1));
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR), PORT2));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
//Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
threadSafeList.add(msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address " + new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
while (true) {
try (DatagramSocket serverSocket = new DatagramSocket()) {
for (Iterator<String> it = threadSafeList.iterator(); !threadSafeList.isEmpty() && it.hasNext(); ) {
String i = it.next();
String msg = "Sent message no " + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(), msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
threadSafeList.remove(i);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
try {
System.out.println("going for sleep");
Thread.currentThread().sleep(500);
System.out.println("going for sleeping");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Design can be modified by changing the creation of sender thread. Whenever receiver thread gets a message, create a sender thread and do the broadcast and shutdown that thread. You can use reusable thread pool instead of fixed Thread pool what used in this example. And you can pass message as argument while you create sender thread (so list may not be needed at all) and do the submit. I do have code.
public static void main(String[] args) throws UnknownHostException,
InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR),
PORT2, executorService));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
And inner classes,
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
private ExecutorService executorService;
public Receiver(InetAddress inetAddress, int port,
ExecutorService executorService) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.executorService = executorService;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
executorService.submit(new Sender(InetAddress
.getByName(INET_ADDR), PORT1, msg));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
private String message;
public Sender(InetAddress inetAddress, int port, String message)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.message = message;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
try {
DatagramSocket serverSocket = new DatagramSocket();
String msg = "Sent message no " + message;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Client has got 2 threads,
One for reading broadcaster messages.
Another for sending 5 messages in loop. Once it is finished, thread will shut-down.
No data exchange here, so no thread safe list.
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver port " + this.port);
byte[] buf = new byte[256];
try (MulticastSocket clientSocket = new MulticastSocket(this.port)) {
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
try {
DatagramSocket serverSocket = new DatagramSocket();
for (int i = 0; i < 5; i++) {
System.out.println("inside loop");
String msg = "Sent message no 2" + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(
msg.getBytes(), msg.getBytes().length, this.addr,
this.port);
System.out.println("Before sending to socket");
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
This article sample code is extended further.
Code to be fine tuned.

JAVA Chat Sever communicates with Iphone clients using TCP protocol

I want to develop demo of JAVA chat server which handles TCP protocol.
Clients will be I-phone.
How can i make communication between JAVA chat server and Objective C ?
I have tried
public class ChatServer {
ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message;
ChatServer() throws IOException {
}
void run() {
try {
// 1. creating a server socket
providerSocket = new ServerSocket(2001, 10);
// 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());
out.flush();
// in = new ObjectInputStream(connection.getInputStream());
sendMessage("Connection successful");
BufferedReader in1 = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
// out = new PrintWriter(socket.getOutputStream(),true);
int ch;
// String line="";
// do{
// ch=in1.read();
// line+=(char)ch;
//
// }while(ch!=-1);
String line = in1.readLine();
System.out.println("you input is :" + line);
// 4. The two parts communicate via the input and output streams
/*
* do { try { message = (String) in.readObject();
* System.out.println("client>" + message); if
* (message.equals("bye")) sendMessage("bye"); } catch
* (ClassNotFoundException classnot) {
* System.err.println("Data received in unknown format"); } } while
* (!message.equals("bye"));
*/
} catch (IOException ioException) {
ioException.printStackTrace();
} finally {
// 4: Closing connection
try {
// in.close();
out.close();
providerSocket.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ChatServer server = new ChatServer();
while (true) {
server.run();
}
}
}
and in objective C i have used
LXSocket *socket;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
socket = [[LXSocket alloc]init];
if ([socket connect:#"127.0.0.1" port:2001]) {
NSLog(#"socket has been created");
}
else {
NSLog(#"socket couldn't be created created");
}
#try {
[self sendData];
}#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[super viewDidLoad];
}
-(IBAction)sendData{
// [socket sendString:#"M\n"];
[socket sendObject:#"Masfds\n"];
}
I am able to communicate but i am getting some unnecessary bits appended with Message which was sent from objective c.
output at server side:
Received from Connection 1.
Received U$nullĂ’
Suggest me some nice ways to resolve this issue.
i have solved this issue with this code:
//Server
package com.pkg;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer {
public static void main(String args[]) {
int port = 6789;
ChatServer server = new ChatServer(port);
server.startServer();
}
// declare a server socket and a client socket for the server;
// declare the number of connections
ServerSocket echoServer = null;
Socket clientSocket = null;
int numConnections = 0;
int port;
public ChatServer(int port) {
this.port = port;
}
public void stopServer() {
System.out.println("Server cleaning up.");
System.exit(0);
}
public void startServer() {
// Try to open a server socket on the given port
// Note that we can't choose a port less than 1024 if we are not
// privileged users (root)
try {
echoServer = new ServerSocket(port);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("Server is started and is waiting for connections.");
System.out
.println("With multi-threading, multiple connections are allowed.");
System.out.println("Any client can send -1 to stop the server.");
// Whenever a connection is received, start a new thread to process the
// connection
// and wait for the next connection.
while (true) {
try {
clientSocket = echoServer.accept();
numConnections++;
Server2Connection oneconnection = new Server2Connection(
clientSocket, numConnections, this);
new Thread(oneconnection).start();
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class Server2Connection implements Runnable {
BufferedReader is;
PrintStream os;
Socket clientSocket;
int id;
ChatServer server;
InputStream isr;
private static final int BUFFER_SIZE = 512; // multiples of this are
// sensible
public Server2Connection(Socket clientSocket, int id, ChatServer server) {
this.clientSocket = clientSocket;
this.id = id;
this.server = server;
System.out.println("Connection " + id + " established with: "
+ clientSocket);
try {
isr = clientSocket.getInputStream();
is = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
}
public void run() {
String line;
try {
boolean serverStop = false;
while (true) {
line = is.readLine();
if (line != null) {
System.out.println("Received " + line + " from Connection "
+ id + ".");
os.println("Hello this is server:" + line);
if (line.equalsIgnoreCase("stop")) {
serverStop = true;
break;
}
} else {
break;
}
// int n = Integer.parseInt(line);
// if (n == -1) {
// serverStop = true;
// break;
// }
// if (n == 0)
// break;
// os.println("" + n * n);
}
System.out.println("Connection " + id + " closed.");
is.close();
os.close();
clientSocket.close();
if (serverStop)
server.stopServer();
} catch (IOException e) {
System.out.println(e);
}
}
}
//client
package com.pkg;
import java.io.*;
import java.net.*;
public class Requester {
public static void main(String[] args) {
String hostname = "localhost";
int port = 6789;
// declaration section:
// clientSocket: our client socket
// os: output stream
// is: input stream
Socket clientSocket = null;
DataOutputStream os = null;
BufferedReader is = null;
// Initialization section:
// Try to open a socket on the given port
// Try to open input and output streams
try {
clientSocket = new Socket(hostname, port);
os = new DataOutputStream(clientSocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + hostname);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + hostname);
}
// If everything has been initialized then we want to write some data
// to the socket we have opened a connection to on the given port
if (clientSocket == null || os == null || is == null) {
System.err.println( "Something is wrong. One variable is null." );
return;
}
try {
while ( true ) {
System.out.print( "Enter an integer (0 to stop connection, -1 to stop server): " );
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String keyboardInput = br.readLine();
os.writeBytes( keyboardInput + "\n" );
// int n = Integer.parseInt( keyboardInput );
// if ( n == 0 || n == -1 ) {
// break;
// }
if(keyboardInput.equalsIgnoreCase("stop")){
break;
}
String responseLine = is.readLine();
System.out.println("Server returns its square as: " + responseLine);
}
// clean up:
// close the output stream
// close the input stream
// close the socket
os.close();
is.close();
clientSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
//objective c client
//
// RKViewController.m
// ConnectServer
//
// Created by Yogita Kakadiya on 10/27/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "RKViewController.h"
#interface RKViewController ()
#end
#implementation RKViewController
- (void)viewDidLoad
{
[super viewDidLoad];
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if ([socket connectToHost:#"192.168.2.3" onPort:6789 error:&err])
{
NSLog(#"Connection performed!");
[socket readDataWithTimeout:-1 tag:0];
}
else
{
NSLog(#"Unable to connect: %#", err);
}
}
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(#"Socket:DidConnectToHost: %# Port: %hu", host, port);
connected = YES;
if(connected)
{
NSData *message = [[NSData alloc] initWithBytes:"Ranjit\n" length:8];
[sock writeData:message withTimeout:-1 tag:0];
}
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(#"SocketDidDisconnect:WithError: %#", err);
connected = NO;
//We will try to reconnect
//[self checkConnection];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
//[self processReceivedData:data];
NSString *readMessage = [[NSString alloc]initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"RECIEVED TEXT : %#",readMessage);
[sock readDataWithTimeout:-1 tag:0];
//NSData *message = data;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end

Categories

Resources