I am trying to establish Server Socket connection between two EC2 instances that I have. On one machine I have Server.java code and the other has Client.java code.
I am not getting any error but the client code is not able to connect to server.
Server.java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class MasterServer {
#SuppressWarnings("unused")
public static void main(String[] args) throws IOException {
// Selector: multiplexor of SelectableChannel objects
Selector selector = Selector.open();
// ServerSocketChannel: selectable channel for stream-oriented listening sockets
ServerSocketChannel channel = ServerSocketChannel.open();
InetSocketAddress addr = new InetSocketAddress(1111);
// Binds the channel's socket to a local address and configures the socket to listen for connections
channel.bind(addr);
// Adjusts this channel's blocking mode.
channel.configureBlocking(false);
int ops = channel.validOps();
SelectionKey selectKy = channel.register(selector, ops, null);
// Infinite loop..
// Keep server running
while(true){
log("i'm a server and i'm waiting for new connection and buffer select...");
// Selects a set of keys whose corresponding channels are ready for I/O operations
selector.select();
// token representing the registration of a SelectableChannel with a Selector
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey myKey = iterator.next();
// Tests whether this key's channel is ready to accept a new socket connection
if (myKey.isAcceptable()) {
SocketChannel client = channel.accept();
// Adjusts this channel's blocking mode to false
client.configureBlocking(false);
// Operation-set bit for read operations
client.register(selector, SelectionKey.OP_READ);
log("Connection Accepted: " + client.getLocalAddress() + "\n");
// Tests whether this key's channel is ready for reading
} else if (myKey.isReadable()) {
SocketChannel client = (SocketChannel) myKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(256);
client.read(buffer);
String result = new String(buffer.array()).trim();
log("Message received: " + result);
if (result.equals("Crunchify")) {
client.close();
log("\nIt's time to close connection as we got last company name 'Crunchify'");
log("\nServer will keep running. Try running client again to establish new connection");
}
}
iterator.remove();
}
}
}
private static void log(String str) {
System.out.println(str);
}
}
Client.java
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
InetSocketAddress addr = new InetSocketAddress("52.201.235.57", 1111);
SocketChannel client = SocketChannel.open(addr);
log("Connecting to Server on port 1111...");
ArrayList<String> companyDetails = new ArrayList<String>();
// create a ArrayList with companyName list
companyDetails.add("Facebook");
companyDetails.add("Twitter");
companyDetails.add("IBM");
companyDetails.add("Google");
companyDetails.add("Crunchify");
for (String companyName : companyDetails) {
byte[] message = new String(companyName).getBytes();
ByteBuffer buffer = ByteBuffer.wrap(message);
client.write(buffer);
log("sending: " + companyName);
buffer.clear();
// wait for 2 seconds before sending next message
Thread.sleep(2000);
}
client.close();
}
private static void log(String str) {
System.out.println(str);
}
}
I am able to connect them locally but not on EC2 machines which is my prime objective. When I run them I get following state
For Server:
^C[root#ip-172-31-59-2 ec2-user]# java Server
i'm a server and i'm waiting for new connection and buffer select...
For Client:
^C[root#ip-172-31-51-12 ec2-user]# java Client
I get no output as there is no connection I think.
Check the "security group" of the EC2 whether the incoming and outgoing rules are configured for the port 1111 to be used.
Related
I have a network programming topic that requires file transfer using TCP and UDP. If TCP send fails then UDP will be executed. I have built each part but I am not sure how can I run the server of TCP and UDP at the same time to be able to receive data of both protocols (my problem is starting 2 server in the master server because I have as the interface). Hope everybody help please .
In one case you need to open a ServerSocket, in the other case a DatagramSocket. It should be possible to open them in parallel, which means you can run both your implementations in parallel running on different threads.
If you are suppose to run the TCP and the UDP Server on the same machine, you will need to use different ports. Then you can start up two different thread, one for each server:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
public class TcpUdpServer {
private final static int UDP_PORT = 8100;
private final static int TCP_PORT = 8200;
public static void main(String[] args) {
new Thread(() -> executeTcpServer()).start();
new Thread(() -> executeUdpServer()).start();
}
public static void executeTcpServer() {
try (ServerSocket serverSocket = new ServerSocket(TCP_PORT)) {
while (true) {
System.out.println("waiting for TCP connection...");
// Blocks until a connection is made
final Socket socket = serverSocket.accept();
final InputStream inputStream = socket.getInputStream();
String text = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
System.out.println(text);
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static void executeUdpServer() {
try (DatagramSocket socket = new DatagramSocket(UDP_PORT)) {
while (true) {
byte[] packetBuffer = new byte[2024];
final DatagramPacket packet = new DatagramPacket(packetBuffer, packetBuffer.length);
System.out.println("waiting for UDP packet...");
// Blocks until a packet is received
socket.receive(packet);
final String receivedPacket = new String(packet.getData()).trim();
System.out.println(receivedPacket);
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
I am writing a web server/client. When communicating over localhost, things are fine. But when communicating using my public IP address, an exception is thrown. Here is a minimal working example:
import java.io.*;
import java.text.*;
import java.util.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws IOException
{
int port = 80;
// server is listening on port
ServerSocket ss = new ServerSocket(port);
// running infinite loop for getting
// client request
while (true)
{
Socket s = null;
try
{
// socket object to receive incoming client requests
s = ss.accept();
System.out.println("A new client is connected : " + s);
// obtaining input and out streams
ObjectOutputStream odos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream odis = new ObjectInputStream(s.getInputStream());
Info info = new Info();
info.color = 1;
odos.writeObject(info);
while(true){
info = (Info)odis.readObject();
if(info.exit){
break;
}
}
// closing resources
odis.close();
odos.close();
}
catch (Exception e){
s.close();
e.printStackTrace();
}
}
}
}
And the Client:
import java.util.*;
import java.net.*;
import java.io.*;
import java.net.InetAddress;
public class Client
{
public static void main(String[] args) {
if(args.length>0){
ip_name = args[0];
}
if(args.length>1){
port = Integer.parseInt(args[1]);
}
network();
}
private static String ip_name = "localhost";
private static int port = 80;
private static void network(){
try
{
System.out.println("Connecting to network");
InetAddress ip = InetAddress.getByName(ip_name);
// establish the connection with server port
Socket s = new Socket(ip, port);
System.out.println("Connected");
// obtaining input and out streams
ObjectOutputStream odos = new ObjectOutputStream(s.getOutputStream());
InputStream i = s.getInputStream();
ObjectInputStream odis = new ObjectInputStream(i);
// get what color we are
int color = ((Info)odis.readObject()).color;
System.out.println(color);
//say we are done
Info info = new Info();
info.exit = true;
odos.writeObject(info);
System.out.println("Shutting down");
}catch(Exception e){
e.printStackTrace();
}
}
}
When using localhost, the client prints out, as expected:
Connecting to network
Connected
1
Shutting down
but when I replace localhost with my public IP:
Connecting to network
Connected
java.io.StreamCorruptedException: invalid stream header: 48545450
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Client.network(Client.java:36)
at Client.main(Client.java:14)
48545450 is hex for "HTTP", but beyond that I can't tell what the problem is. Any ideas?
When I tried running your code I got error "Info is non-serilizable". I have modified your Info class as follows.
import java.io.Serializable;
public class Info implements Serializable {
public int color;
public boolean exit;
}
You need to implement Serializable If you are sending class data. Using this you can persist object info over a network.
I have designed a Java Client class that is required to send a byte[] array to a Java Server class via a socket. Here is my code:
ByteArrayClient.java
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ByteArrayClient {
public static void main(String[] args) {
//make POJO__________________________
ByteEncodeSubscriptionReq sr1=ByteEncodeSubscriptionReq.makeRequest(103, "Str1", "Str2");
//Connection details____________________
String serverName = "localhost";
int port = 6060;
try {
//Establish Connection with server_______________________________
System.out.println("ByteArrayClient: Connecting to " + serverName +":" + port+"...");
Socket client = new Socket(serverName, port);//make new socket
System.out.println("ByteArrayClient: connected to " + client.getRemoteSocketAddress());
//Encode POJO to ByteArray________________________________
byte[] SubscripReqByteArray=ByteEncodeSubscriptionReq.encode(sr1);
//encoded correctly to a 44 bit byte array
System.out.println("ByteArrayClient: SubscripTionRequest successfully encoded");
//Send POJO ByteArray to server__________________________
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.write(SubscripReqByteArray);;
System.out.println("ByteArrayClient: POJO sent to server");
//Receive Server response_________________________________
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("ByteArrayClient received: " + in.readUTF());
//close socket____________________________________
client.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("PojoClient: Connection Failed");
}
}
}
...and ByteArrayServer.java
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class ByteArrayServer extends Thread{
private ServerSocket serverSocket;
public ByteArrayServer(int port) throws IOException {
serverSocket = new ServerSocket(port);//create server socket
serverSocket.setSoTimeout(15000);//socket closes after 15 seconds
this.start();
}
public void run() {
while (true) {//server runs infinitely______________
try {
System.out.println("ByteArrayServer: Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket servedClient = serverSocket.accept();//client socket
System.out.println("ByteArrayServer: connected to " + servedClient.getRemoteSocketAddress());
//Receive Client ByteArray___________________________________________
ByteEncodeSubscriptionReq receivedReq=new ByteEncodeSubscriptionReq();//server side POJO
System.out.println("ByteArrayServer: created SubscriptionReq Object");
InputStream PojoStreamHolder = servedClient.getInputStream();
System.out.println("ByteArrayServer: client InputStream received");
byte[] clientByteStream=new byte[44];//same size as Pojo byte requirement
_____/*MY CODE IS STUCK SOMEWHERE HERE*/__________
servedClient.getInputStream().read(clientByteStream);
System.out.println("ByteArrayServer: clientByteStream received: "+clientByteStream[0]+" "+clientByteStream[1]);
receivedReq=ByteEncodeSubscriptionReq.decode(clientByteStream);
//Send confirmation to Client__________________________________________________
DataOutputStream out = new DataOutputStream(servedClient.getOutputStream());
if(receivedReq.getRequestSymbol().trim().length()!=0){
out.writeUTF("ByteArrayServer received Subscription ID="+receivedReq.getSubscriptionID());
System.out.println("ByteArrayServer: new SubscriptionRequest ID="+receivedReq.getSubscriptionID()+" Subscriber_Name="+receivedReq.getSubscriberName());
}else{
out.writeUTF("ByteArrayServer: did not receive Subscription ID");
}
//Close Client socket_________________________________________________________
//server.close();
//serverSocket.close();
} catch (SocketTimeoutException s) {
System.out.println("PojoServer: Socket timed out after " + getTimeElapsedInSeconds(startTime) + " seconds from start");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String[] args) {
// int port = Integer.parseInt(args[0]);//to get port as an Argument
int port = 6060;
try {
Thread t = new ByteArrayServer(port);
startTime = System.currentTimeMillis();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is the Server console output:
ByteArrayServer: Waiting for client on port 6060...
ByteArrayServer: connected to /127.0.0.1:64233
ByteArrayServer: created SubscriptionReq Object
ByteArrayServer: client InputStream received
The issue is that while the Stream is received by the server without errors, it gets stuck near servedClient.getInputStream().read(clientByteStream); method and does not proceed further.
I've also tried
int count=servedClient.getInputStream().read(clientByteStream);
and
DataInputStream in = new DataInputStream(servedClient.getInputStream());
long bStr=in.readLong();
and
ObjectInputStream PojoObjHolder = new ObjectInputStream(PojoStreamHolder);
byte[] clientByteStream2 = (byte[])PojoObjHolder.readObject();
..but they show the same problem as well.
How should I pass the Byte Array between the two classes without extra imports?
The problem was in my ByteArrayClient Class. I had to link the OutputStream with the client socket, rather than creating a new instance of it. So I replaced:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.write(SubscripReqByteArray);;
with
OutputStream os = client.getOutputStream(out);
os.write(SubscripReqByteArray);;
Thank you for the hint Ekant
DataInputStream.readFully(byte[] b) will finish only when in inputstream bytes till b.length available. So for sure you need to debug if you have all the bytes or not.And the solution is to make those byte available so that the function will finish.
Same for DataInputStream.read(byte[] b) The method is blocked until input data is available.
Please make sure by debugging your app that inputstream have 44 bytes.
Try below to count available bytes and you can read those easily.
// count the available bytes form the input stream
int count = is.available();
// create buffer
byte[] bs = new byte[count];
// read data into buffer
dis.read(bs);
I try to create a program which is based on client/server communication.
In this program I have several clients and several servers.
At the beginning of the program some clients go up, and wait for new connections from different servers.
When the first server goes up, I want him to know who is the clients that are available in the network, and then it begins to communicate with all these clients in tcp protocol (ServerSocket).
However, if a new clients goes up, this server should know about it.
The same happens when new servers go up.
My first think, is to use multicast commnication. The client will send every 5 seconds a broadcast to the networks and the servers will listen to these messages.
My broblem is how to combine these two methods (multicast and tcp) in order to built this program.
Should I use two differnet ports one for the multicast, and one for the tcp protocol?
Is it possible to allow the server\client to listen for different communication (multicast or tcp) with treads?
I just need a litle push, and some basic code in order to begin this...
EDIT: OK, I succeeded to built a multicast comunication.
The agent goes up, and send every 5 seconds its name.
the server goes up, and receives the agent's broadcast.
If a new agent goes up, the server know about it.
The code look like this:
Agent code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
public class Agent {
private static int portMulticasting = 1004;
private DatagramSocket socket;
private boolean broadcast = true;
private String group = "230.0.0.1"; //group address
private int delay = 5000;
public Agent(){
try{
socket = new DatagramSocket();
System.out.println("agent ready");
}
catch (SocketException e){
e.printStackTrace();
System.exit(1);
}
}
public void start(String agentName){
DatagramPacket packet;
try{
InetAddress address = InetAddress.getByName(group);
while (broadcast){
byte[] buf = new byte[256];
buf = agentName.getBytes();
packet = new DatagramPacket(buf,buf.length,address,portMulticasting);
socket.send(packet);
try{
Thread.sleep(delay);
} catch (InterruptedException e){
System.exit(0);
}
}
socket.close();
} catch (IOException e){
e.printStackTrace();
}
}
public static void main (String[] args) throws IOException {
System.out.println("Enter name of the new agent: ");
Scanner sc = new Scanner(System.in);
String agentName = sc.nextLine();
Agent agent = new Agent();
agent.start(agentName);
}
}
Server Code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
String groupIP = "230.0.0.1";
int portMulticasting = 1004;
if (args.length > 0)
groupIP = args[0];
try{
//get a multicast socket and join group
MulticastSocket socket = new MulticastSocket(portMulticasting);
InetAddress group = InetAddress.getByName(groupIP);
socket.joinGroup(group);
//get packet
DatagramPacket packet;
while (true){
byte[] buf = new byte[256];
packet = new DatagramPacket(buf,buf.length);
socket.receive(packet);
buf = packet.getData();
int len = packet.getLength();
String received = (new String(buf)).substring(0,len);
try{
System.out.println("Agent name: " + received);
} catch (NumberFormatException e){
System.out.println("cannot interpret number");
}
}
socket.leaveGroup(group);
socket.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
Now, I want that the agents continue to send broadcast every 5 seconds, but meanwhile the server begin to work with the agents (send messages, ask for information from the agents etc).
I'm new with Java NIO, after reading some tutorials, I've tried my own to write a simple NIO server and client.
My server just does a simple thing is listen from client and print to console, and the client just connects to server and send to it 3 messages "Hello".
The problem is my server listens and works well with the 3 messages, after that it should be blocked and continue listening, but it does not, there's no blocking, it runs it while loop infinitely. Here's my server and client:
Server
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class Server {
public static void main(String args[]) throws Exception {
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new InetSocketAddress(8000));
System.out.println("Server actives at port 8000");
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// print
System.out.println("[ " + keys.size() + " ]");
// For each keys...
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// if isAccetable = true
// then a client required a connection
if (key.isAcceptable()) {
// get client socket channel
SocketChannel client = server.accept();
// Non Blocking I/O
client.configureBlocking(false);
// recording to the selector (reading)
client.register(selector, SelectionKey.OP_READ);
continue;
}
// if isReadable = true
// then the server is ready to read
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
// Read byte coming from the client
int BUFFER_SIZE = 1024;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try {
client.read(buffer);
} catch (Exception e) {
// client is no longer active
e.printStackTrace();
}
// Show bytes on the console
buffer.flip();
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
System.out.println("[" + charBuffer.toString() + "]");
}
}
}
}
}
And here's my client:
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class Client {
public static void main(String args[]) throws Exception {
// Create client SocketChannel
SocketChannel client = SocketChannel.open();
// nonblocking I/O
client.configureBlocking(false);
// Connection to host port 8000
client.connect(new java.net.InetSocketAddress("127.0.0.1", 8000));
// Create selector
Selector selector = Selector.open();
// Record to selector (OP_CONNECT type)
SelectionKey clientKey = client.register(selector,
SelectionKey.OP_CONNECT);
int counter = 0;
boolean chk = true;
// Waiting for the connection
while (selector.select(500) > 0 && chk) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// For each key...
while (i.hasNext() && chk) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// Get the socket channel held by the key
SocketChannel channel = (SocketChannel) key.channel();
// Attempt a connection
if (key.isConnectable()) {
// Connection OK
System.out.println("Server Found");
// Close pendent connections
if (channel.isConnectionPending())
channel.finishConnect();
// Write continuously on the buffer
ByteBuffer buffer = null;
for (;chk;counter++) {
Thread.sleep(1000);
buffer = ByteBuffer.wrap(new String(" Client ").getBytes());
channel.write(buffer);
buffer.clear();
if (counter == 2)
{
chk = false;
client.close();
}
}
}
}
}
}
}
Anyone can explain what is wrong with my code?
Thanks in advance.
You are probably getting an endless stream of EOS-s from the accepted socket channel. You are ignoring the result of read(). You must at least check it for -1 and if so close the channel.
NIO socket apis are non-blocking. The selector returns the keys that are ready for operation. In case there is nothing ready then it will just keep looping. This is the expected behaviour.
no blocking because of
server.configureBlocking(false);
in Server.main()