Multithreading Java Socket - java

I have been asked to take this post down, and in particular the code, by a superior of mine
Problem 1: Client did not receive message
Solution: Make sure port matches sending's port
Problem 2: Could not broadcast message
Solution: Use a broadcast address

// Client REceive
DatagramSocket socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress("127.0.0.1", 4002));
// ClientSEnd
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);

Just add the port number to the Datagram socket in the receive. it will work fine.
Class - ClientReceive:
DatagramSocket socket = new DatagramSocket(4001);

Set the reuse address to true ..
that will make use of the address whatever it is 4001 4002..etc
socket.setReuseAddress(true);

The problem seems to be that DatagramSocket allows you to send a datagram to a given destination. In your case you are sending to localhost, so that all messages are sent to the local machine only and not to other clients. If you want to reach all network clients should use a broadcast address or use the MulticastSocket class instead DatagramSocket.

import java.net.*;
import java.io.*;
public class ClientSend implements Runnable
{
private Thread t;
private DatagramSocket socket;
private String name;
private String sendingMessage;
private int port;
public ClientSend(int port)
{
this.port = port;
}
public void run()
{
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
socket = new DatagramSocket();
socket.setReuseAddress(true);
while(true)
{
sendingMessage = br.readLine();
byte sendingData[] = sendingMessage.getBytes();
InetAddress clientAddress = InetAddress.getByName("224.0.0.3");
DatagramPacket sendingPacket = new DatagramPacket(sendingData, sendingData.length, clientAddress, 4011);
socket.send(sendingPacket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientSend CS = new ClientSend(4011);
CS.start();
}
}
import java.net.;
import java.io.;
public class ClientReceive implements Runnable
{
private Thread t;
public ClientReceive()
{
}
public void run()
{
try {
// DatagramSocket socket = new DatagramSocket(null);
MulticastSocket socket = new MulticastSocket(4011);
InetAddress group = InetAddress.getByName("10.10.222.120");
socket.joinGroup(group);
//socket.setReuseAddress(true);
//socket.bind(new InetSocketAddress("10.10.222.120", 4011));
while(true)
{
byte receivingData[] = new byte[1024];
DatagramPacket receivingPacket = new DatagramPacket(receivingData, receivingData.length);
socket.receive(receivingPacket);
String receivingMessage = new String(receivingPacket.getData(), 0, receivingPacket.getLength());
System.out.println("Received: " + receivingMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void start()
{
t = new Thread(this);
t.start();
}
public static void main(String args[]) throws Exception
{
ClientReceive CR = new ClientReceive();
CR.start();
}
}

Related

Server won't connect to more than one client (Java)

my server class
import java.net.*;
import java.io.*;
public class server
{
private Socket socket;
private ServerSocket server;
// constructor with port
public void start(int port){
try {
server = new ServerSocket(port);
while(true){
socket = server.accept();
new ConnectionHandler(socket).run();
}
}catch(IOException i){
}
}
}
class ConnectionHandler implements Runnable{
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream in = null;
public ConnectionHandler(Socket socket){
this.socket=socket;
}
#Override
public void run() {
InputStream inp = null;
BufferedReader brinp = null;
DataOutputStream out = null;
try
{
System.out.println("Waiting for a client ...");
System.out.println(server);
System.out.println("Client accepted");
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String line = "";
// reads message from client until "Over" is sent
while (!line.equals("Over"))
{
try
{
line = in.readUTF();
System.out.println(line);
}
catch(IOException i)
{
System.out.println(i);
}
}
System.out.println("Closing connection");
// close connection
socket.close();
in.close();
}
catch(IOException i)
{
System.out.println(i);
}
}
public static void main(String[] args) {
server serverr = new server();
serverr.start(4000);
}
}
Here's my client class.
import java.net.*;
import java.io.*;
public class Client
{
// initialize socket and input output streams
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream out = null;
// constructor to put ip address and port
public Client(String address, int port)
{
// establish a connection
try
{
socket = new Socket(address, port);
System.out.println("Connected");
// takes input from terminal
input = new DataInputStream(System.in);
// sends output to the socket
out = new DataOutputStream(socket.getOutputStream());
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
// string to read message from input
String line = "";
// keep reading until "Over" is input
while (!line.equals("Over"))
{
try
{
line = input.readLine();
out.writeUTF(line);
}
catch(IOException i)
{
System.out.println(i);
}
}
// close the connection
try
{
input.close();
out.close();
socket.close();
}
catch(IOException i)
{
System.out.println(i);
}
}
public static void main(String args[])
{
Client client = new Client("127.0.0.1", 4000);
}
}
Trying to develop pretty simple chat application works via terminal, but I think there are plenty of bugs I have in my code.
The server can handle one client, but when another client comes up it doesn't connect to other clients.
What am I have to do now?
I couldn't find out where my problem is, waiting your helps.
Note: I am completely new to socket programming concept.
The ConnectionHandler class is a thread class, and you must wrap its object to a Thread instance and then call start() instead of run().
So in the Server class change
new ConnectionHandler(socket).run();
with
new Thread(ConnectionHandler(socket)).start();

How to stop continuous execution of while loop with same connection

I am making a server for a Chat application in Java.
The while loop is supposed to connect to new clients but the code keeps connecting to the first client repeatedly even after it has connected resulting in Bind Failed error. What should I change?
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ServerM
{
public static void main(String args[])
{
while(true)
{
Listener l = new Listener();
l.run();
}
}
}
class Listener implements Runnable
{
static InetAddress arr[] = new InetAddress[10];
static int i = 0;
public void run()
{
try
{
ServerSocket ss = new ServerSocket(44444);
System.out.println("Waiting...");
Socket s = ss.accept();
System.out.println("Connected!\n");
DataInputStream din=new DataInputStream(s.getInputStream());
String ip = din.readUTF();
InetAddress addr = InetAddress.getByName(ip);
for(int j=0; j<=i; j++)
{
if(arr[j] == addr)
return;
}
arr[i++] = addr;
ChatThread c = new ChatThread(addr,s);//This creates a thread to allow communication with Client
c.run();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Your problem is in the design of the solution. You are running a multiple instances of the Server Socket (and using the same port, what will end in an exception) and using this thread for getting the client connections, therefore you can only have one connection.
What you should do is, run a Thread for the Server Socket who will listen for all the connections, and then run every client instance (new Thread) in an infinite loop.
public class ServerM
{
public static void main(String args[])
{
Listener l = new Listener();
l.run();
}
}
class Listener implements Runnable
{
static InetAddress arr[] = new InetAddress[10];
static int i = 0;
public void run()
{
try
{
ServerSocket ss = new ServerSocket(44444);
System.out.println("Waiting...");
while (true) {
Socket s = ss.accept();
ClientListener clientListener = new ClientListener(s);
clientListener.run();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class ClientListener implements Runnable {
private Socket socket;
public ClientListener(Socket socket) {
this.socket = socket;
}
public void run() {
System.out.println("Connected!\n");
DataInputStream din=new DataInputStream(s.getInputStream());
String ip = din.readUTF();
InetAddress addr = InetAddress.getByName(ip);
for(int j=0; j<=i; j++)
{
if(arr[j] == addr)
return;
}
arr[i++] = addr;
ChatThread c = new ChatThread(addr,socket);
c.run();
}
}
You have to do this because you only need one instance of ServerSocket listening for new connections at a specific port, and then you need [1..n] client instances for handling each connection.
Catch Exception is bad practice
catch(Exception e)
{
e.printStackTrace();
}
Try to forward an custom exception (MyException.class) to the top level and handle this exception in ServerM class in try..catch. And don't forget to close socket in finally block
ss.close();
s.close();

Bind Exception when trying to send UDP packet

I am making a peer to peer chat application for which I have written the below code for chat with one person. This code works for localhost(127.0.0.1) but doesn't work for any specific ip address(192.168.43.118) and throws bindexception. Please help.
import java.sql.*;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class communicate {
public static void main(String args[]) throws Exception {
communicate ob = new communicate();
String ip = "192.168.43.118";
ob.text(ip);
}
public void text(String friend_ip) throws Exception{
System.out.println("Press 'Exit' to exit the chat");
int send_port = 40002;
int receive_port = 40002;
//InetAddress inetaddr = InetAddress.getByName(friend_ip);
byte[] ipAddr = new byte[] { (byte)192, (byte)168, (byte)43, (byte)118 };
System.out.println(ipAddr.length);
InetAddress inetaddr = InetAddress.getByAddress(ipAddr);
System.out.println("B");
DatagramSocket serverSocket = new DatagramSocket(receive_port, inetaddr);
System.out.println("YO");
Runnable send = new SendMsg(send_port, friend_ip, serverSocket);
Runnable receive = new GetMsg(friend_ip, receive_port, serverSocket);
Thread t1 = new Thread(send);
Thread t2 = new Thread(receive);
t1.start();
t2.start();
}
class SendMsg implements Runnable {
private DatagramSocket senderSocket;
private int send_port;
private String sendto_ip;
SendMsg(int port, String friend_ip, DatagramSocket ds)throws Exception {
senderSocket = new DatagramSocket(64432);
send_port = port;
sendto_ip = friend_ip;
}
public void run(){
try {
while(true) {
String sendString;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
sendString = br.readLine();
byte[] sendData = sendString.getBytes();
byte[] ipAddr = new byte[] { (byte)192, (byte)168, (byte)43, (byte)118 };
InetAddress inetAddress = InetAddress.getByAddress(ipAddr);
DatagramPacket sendPacket = new DatagramPacket (sendData, sendData.length, inetAddress, send_port);
senderSocket.send(sendPacket);
System.out.println("Message Sent");
}
}
catch(Exception e) {
System.out.println("Exc at Sender\n" + e);
}
finally {
if(senderSocket != null) senderSocket.close();
}
}
}
class GetMsg implements Runnable{
private DatagramSocket serverSocket;
private String friend_ip;
private int receive_port;
GetMsg(String ip, int port, DatagramSocket ds) throws Exception{
friend_ip = ip;
receive_port = port;
serverSocket = ds;
}
public void run(){
try {
while(true) {
byte[] receiveData = new byte[10000];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String message = new String (receivePacket.getData(), 0, receivePacket.getLength());
System.out.println(friend_ip + ": " + message);
}
}
catch(Exception e) {
System.out.println("Exc at Rec\n" + e);
}
finally {
if(serverSocket != null) serverSocket.close();
}
}
}
}
When I run it on terminal the following output is shown
Press 'Exit' to exit the chat
4
B
Exception in thread "main" java.net.BindException: Cannot assign requested address (Bind failed)
at java.base/java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.base/java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:131)
at java.base/java.net.DatagramSocket.bind(DatagramSocket.java:394)
at java.base/java.net.DatagramSocket.<init>(DatagramSocket.java:244)
at java.base/java.net.DatagramSocket.<init>(DatagramSocket.java:301)
at communicate.text(communicate.java:21)
at communicate.main(communicate.java:10)
As "YO" is not printed it seems that error is in the text method where I am trying to create DatagramSocket. Where am I going wrong?
If you want read, do not bind the remote address. Just create a local UDP socket (it will be a server socket) and just read from/write to its buffer. You can bind to your local network interface only and these must be initialized before. So you cannot bind to an unused Wifi, or unplugged ethernet adapter.
If you want test a sender, and a receiver in the same java program on different threads, you have to use two different socket.
A hint: use InetAddress.getByName(IPv4) for string IP input, you do not need the byte array.

Android UDP socket

Hi there currently i am creating a UDP connection for my program currently its localhost how am i going to insert my IP address so that another computer in the same network will be able to receive the message i type at the server side.
UDPSERVER
package testing;
import java.io.*;
import java.net.*;
public class UdpServer {
public static void main(String args[]) {
String str;
try {
BufferedReader Br;
Br = new BufferedReader(new InputStreamReader(System. in ));
DatagramSocket Sock;
Sock = new DatagramSocket(1000);
DatagramPacket Dp;
System.out.println("Enter the data..... Enter 'exit' to stop");
while (true) {
str = Br.readLine();
Dp = new DatagramPacket(str.getBytes(), str.length(),
InetAddress.getByName("localhost"), 2000);
Sock.send(Dp);
if (str.equals("exit")) break;
}
Sock.close();
} catch (Exception e) {}
}
}
UdpClient
package testing;
import java.net.*;
public class UdpClient {
public static void main(String arg[]) {
String str;
DatagramSocket Sock;
DatagramPacket Dp;
try {
Sock = new DatagramSocket(2000);
byte Buff[] = new byte[1024];
System.out.println("Client ready...");
while (true) {
Dp = new DatagramPacket(Buff, 1024);
Sock.receive(Dp);
str = new String(Dp.getData(), 0, Dp.getLength());
System.out.println(str);
if (str.equals("exit")) break;
}
Sock.close();
} catch (Exception e) {
System.out.println("Connection failure...");
} finally {
System.out.println("Server Disconnected...");
}
}
}
The first step is to try and hardcode the ip of the other computer and test. If that works then look at adding UDP Broadcast Discovery. Here's an example in java:
http://michieldemey.be/blog/network-discovery-using-udp-broadcast/
The idea is that all devices that need to talk broadcast on UDP. Once they hear the broadcast, they need to connect to eachother. Usually one side will need to be pre-determined as the server, and the other as the client.

Client-Server Multi-Threading

I am having a problem implementing a simple multi threaded server in Java.
My idea is for a server to broadcast a message to all clients(without the use of a multicast).
For this I am implementing a broadcast method. This method will use a for loop, and loop through each client Thread, which I have stored in a collection. It will call each threads send(), which outputs writeUTF().
My problem is for 2 clients A+B.
A outputs: hello
B outputs: hi there
B will not recieve hello, and when B type again, it will the recieve A's message.Code example:
import java.net.*;
import java.io.;
import java.util.;
public class ServerThreadHandler extends Thread {
private AuctionServer server = null;
private Socket socket = null;
private String name = null;
private int ID = -1;
private DataInputStream dataIn = null;
public DataOutputStream dataOut = null;
private Thread thread;
protected static Vector handlers = new Vector();
// reason server is used here is because ian was calling a server method broadcast
// from inside the
public ServerThreadHandler(AuctionServer server, Socket socket, String name) throws IOException{
this.server = server;
this.socket = socket;
this.name = name;
dataIn = new DataInputStream( new
BufferedInputStream(socket.getInputStream()));
dataOut = new DataOutputStream(socket.getOutputStream());
}
// handles a specific client.
public void run(){
System.out.println("Server running..");
while(true){
try{
// broadcast to all clients. This will only be one client in this case.
server.broadcast(dataIn.readUTF());
int pause = (int)(Math.random() * 3000);
Thread.sleep(pause);
}
catch(IOException e){
System.out.println(e.getMessage());
}
catch(InterruptedException e){
System.out.println(e.getMessage());
}
}
}
public void send(String msg){
try{
dataOut.writeUTF(msg);
dataOut.flush();
}
catch(IOException e){
}
}
Server code:
// broadcast this to clients.
public void broadcast(String msg){
for(int i = 0; i < clientCount; i++){
clients[i].send(msg);
}
}
Where clients[] is
private ServerThreadHandler clients[] = new ServerThreadHandler[3];
I'm going to give you a rough outline, you can fill in the rest of the details:
public class Server {
private ServerSocket serverSocket;
private List<Socket> clientSockets;
// constructor(s)
private class ThreadTask implements Runnable {
private Socket clientSocket;
public ThreadTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
while(true) {
// read message from clientSocket
for(Socket peerSocket: clientSockets) {
// send message on peerSocket
}
}
}
}
private void acceptConnections() {
while(true) {
try {
Socket clientSocket = serverSocket.accept();
clientSockets.add(clientSocket);
Thread t = new Thread(new ThreadTask(clientSocket));
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Categories