I'm learning Sockets programming in Java. I'm trying to solve a problem that consists in:
Having a server that accepts a connection from one client on a
time. That part is solved.
Now I want the server to receive a sequence of integers in text
format that will finish when a end of file situation on the socket
reader stream is detected.
I'm trying to do this using DataInputStream and
DataOutputStream because thats the only thing that I know so far.
Can somebody help? I don't know how to the 2nd part of my problem.
I have the following code:
public class Exercise{
public static void main(String args[]) throws Exception {
ServerSocket server= new ServerSocket(6789);
while(true) {
try {
Socket aux= server.accept();
DataInputStream dis = new DataInputStream(aux.getInputStream());
DataOutputStream dos = new DataOutputStream(aux.getOutputStream());
while(dis != null) {
}
}
catch (EOFException e) {
out.println("The client finish execution!");
continue;
}
}
}
}
You need to define a protocol of data exchange. That's how all of the networking applications work. The client and server have to agree on a FORMAT and SEQUENCE of data that will be exchanged. The most basic thing you can do is send the following in sequence
START
1,2,3,4,5,6
STOP
The moment you receive START, you know the next input line is your sequence of integers which you can parse using your custom logic.
Once you receive STOP you know there wont be any more data and you stop and return the response/acknowledgement to the client.
Have a look at this page from the oracle website http://www.oracle.com/technetwork/java/socket-140484.html#server should have all the info you need to setup and receive String data from a socket connection.
To process a sequence of integers, would depend on the formatting, so you would want to make sure that they are seperated by space or some standard delimiter like white-space or comma (i.e. "1 2 3 4" or "1,2,3,4") and then use the StringTokenizer or a similar class to break up the String into individual integer Strings and then parse with Integer.parseInt();
Related
I'm trying to write a socket program in Java that intercepts data/packets.
I've successfully written this in python:
import socket
def createListener(port):
srvSock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
srvSock.bind(('localhost', port))
srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
while True:
raw_data, addr = srvSock.recvfrom(65536)
print('data: ' , raw_data)
createListener(80)
This is my basic Java socket program
public static void main(String[] args) {
try{
ServerSocket ss = new ServerSocket(80);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str = (String)dis.readUTF();
System.out.println("data: "+str);
ss.close();
} catch(IOException i){
System.out.println(i);
}
}
However, when run, it doesn't intercept all data moving through the port on the network like the python program does. Specifically this line srvSock.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) in the Python script enables the socket to listen to the port and capture/intercept the entirety of the data going through it.
I cannot find a Java alternative to this syntax or any solution to my problem at all for that matter.
I would appreciate any help in how to use sockets to intercept packets on a network port.
Thanks
Im fairly certain what you are trying to do cannot be done with Java. It looks like you are trying to use "promiscuous mode", but Java sockets cannot be started in promiscuous mode. Java sockets are an end-to-end implementation: they can't listen on the network port for all traffic. For sure the network port would have to be in promiscuous mode, but I don't think Java is the right choice for you.
The only thing I can think of that might get you there would be doing a native call in something like JNI, but I wouldn't even really know where to start with that.
Here is a really old post that I found that is kind of related: java socket and web programing
From the looks of it, you're trying to read incoming bytearrays as string lines.
If that is so, this is what I do to read lines without missing a single line (In Kotlin):
socket.getInputStream().bufferedReader(Charsets.UTF_8).forEachLine {
it -> { /* Do what you wanna do with the input */ }
}
In Java, it's much less abstract :
BufferedReader(InputStreamReader(socket.getInputStream(), Charsets.UTF_8), 8 * 1024)
Then, use lines from this buffered reader as a line sequence to read your incoming lines.
I'm very new to networking in java and wanted to create a network chat program, I have found a few tutorials online and kind of drifted from that. I have the server of my program working and the only thing that is interfering is when I try to read the chat messages that the server sends over. The server does send the bytes of data over since the print message does work. So the problem is that the while loop never ends, what can this be a problem of?
public String[] updateChatDialog() throws IOException{
String returnString = "";
int accessed = -1;
while((accessed = in.read()) > 0){
System.out.println((char)accessed);
returnString = returnString + (char)accessed;
}
System.out.println(returnString);
return stringToTable(returnString);
}
Any tips on java networking would be helpful!
I do reset the BufferedInputStream every time the chats are rendered into a string, AKA the method above with the return in it.
The 'problem' is that your loop reads until end of stream, and the peer isn't closing the connection so EOS never arrives.
If you want to read messages you have to define them yourself. The easiest thing for you to do in this application is write and read lines, with e.g. PrintWriter.println() and BufferedReader.readLine().
I am trying to implement a multisocket program (both client and server). After a little googling, I found that a good idea to do it is to implement Runnable. Now I suppose that each thread I create and use .start() is a different client (correct me if I'm wrong).
What I find difficult is to understand 2 things:
-Which is the exact line that accepts data? I guess it's not the Server.accept() method since this method is used to initiate a connection with the specific client (by making a new thread as mentioned before).
-How can I accept more than 1 packet (let's say it's a string)?
A little correction, every new thread you create and start with start() will be a new server thread handling a new client.
Which is the exact line that accepts data?
To accept data from client, you'll have to wrap the client's input stream into some input stream and then call the input stream's respective read function.
void readx(Socket con)
{
String line=new String();
BufferedReader bin= new BufferedReader(new InputStreamReader(con.getInputStream());
while((line = bin.readLine()) != null) //Read new lines coming from the server
System.out.println(line);
}
This is just an example, you can have other InputStream wrappers like DataInputStream and their respective read functions.
How can I accept more than 1 packet (let's say it's a string)?
The above snippet will continuously accept data from client(can be any number of lines) till the client sends an End of Stream character.
When working with Sockets in Java, how can you tell whether the client has finished sending all (binary) data, before you could start processing them. Consider for example:
istream = new BufferedInputStream (socket.getInputStream());
ostream = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[BUFFER_SIZE];
int count;
while(istream.available() > 0 && (count = istream.read(buffer)) != -1)
{
// do something..
}
// assuming all input has been read
ostream.write(getResponse());
ostream.flush();
I've read similar posts on SO such as this, but couldn't find a conclusive answer. While my solution above works, my understanding is that you can never really tell if the client has finished sending all data. If for instance the client socket sends a few chunks of data and then blocks waiting for data from another data source before it could send more data, the code above may very well assume that the client has finished sending all data since istream.available() will return 0 for the current stream of bytes.
Yes, you're right - using available() like this is unreliable. Personally I very rarely use available(). If you want to read until you reach the end of the stream (as per the question title), keep calling read() until it returns -1. That's the easy bit. The hard bit is if you don't want the end of the stream, but the end of "what the server wants to send you at the moment."
As the others have said, if you need to have a conversation over a socket, you must make the protocol explain where the data finishes. Personally I prefer the "length prefix" solution to the "end of message token" solution where it's possible - it generally makes the reading code a lot simpler. However, it can make the writing code harder, as you need to work out the length before you send anything. This is a pain if you could be sending a lot of data.
Of course, you can mix and match solutions - in particular, if your protocol deals with both text and binary data, I would strongly recommend length-prefixing strings rather than null-terminating them (or anything similar). Decoding string data tends to be a lot easier if you can pass the decoder a complete array of bytes and just get a string back - you don't need to worry about reading to half way through a character, for example. You could use this as part of your protocol but still have overall "records" (or whatever you're transmitting) with an "end of data" record to let the reader process the data and respond.
Of course, all of this protocol design stuff is moot if you're not in control of the protocol :(
I think this is the task more of a protocol, assuming that you are the man who writes both the transmitting and receiving sides of application.
For example you could implement some simple logic protocol and divide you data into packets. Then divide packets into two parts: the head and the body. And then to say that your head consists of a predefined starting sequence and contains number of bytes in the body. Of forget about starting sequence and simpy transfer number of bytes in the bofy as a first byte of the packet.
Then you've could solve you problem.
As some ppl already said you can't avoid some kind of protocol for communication.
It should look like this for example:
On the server side you have:
void sendMSG(PrintWriter out){
try {
//just for example..
Process p = Runtime.getRuntime().exec("cmd /c dir C:");
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
//and then send all this crap to the client
String s = "";
while ((s = br.readLine()) != null) {
out.println("MSG");
out.println(s);
}
} catch (Exception e) {
System.out.println("Command incorrect!");
}
out.println("END");
}
//You are not supposed to close the stream or the socket, because you might want to send smth else later..
On the client side you have:
void recieveMSG(BufferedReader in) {
try {
while (in.readLine().equals("MSG")) {
System.out.println(in.readLine());
}
} catch (IOException e) {
System.out.println("Connection closed!");
}
}
as Nikita said this is more of task of protocol. Either you can go by header and body approach or you can send a special character or symbol for end of stream to break processing loop. Something like if you send say '[[END]]' on socket to denote end of stream.
In Java, how would you set up a socket listener that listened to a socket for a series of bytes that represented a command and on recieving called a method which parsed the incoming data and invoked the appropriate command?
Clarification:
My issue is not with handling the commands (Which might also be error codes or responses to commands from the server) but with creating the socket and listening to it.
More Clarification:
What I want to do is mimic the following line of .Net (C#) code:
_stream.BeginRead(_data,0, _data.Length, new
AsyncCallback(this.StreamEventHandler), _stream);
Where:
_stream is a network stream created from a socket
_data is an array of Byte of length 9
this.StreamHandler is a delegate (function pointer) which get executed when data is read.
I am rewriting a library from C# into Java and the component I am currently writing passes commands to a server over TCPIP but also has to be able to bubble up events/responses to the layer above it.
In C# this seems to be trivial and it's looking less and less so in Java.
Starting from my other answer: The specific part you request is the one that goes into the section: "Magic goes here". It can be done in ohh so many ways, but one is:
final InputStream in = socket.getInputStream();
// This creates a new thread to service the request.
new Thread(new Runnable(){
public void run(){
byte[] retrievedData= new byte[ITEM_LENGTH];
in.read(retrievedData, 0, ITEM_LENGTH);
in.close();
// Here call your delegate or something to process the data
callSomethingWithTheData(retrievedData);
}
}).start();
Have a small main method which sets up the socket and listens for incoming connections. Pass each connection to a worker object (possibly in its own thread).
The worker object should have two APIs: The server and the client. The client API gets a connection and reads data from it, the server API takes a connection and writes data to it.
I like to keep these two in a single class because that makes it much more simple to keep the two in sync. Use a helper class to encode/decode the data for transmission, so you have single point to decide how to transmit integers, commands, options, etc.
If you want to go further, define a command class and write code to serialize that to a socket connection and read it from it. This way, you worker objects just need to declare which command class they handle and the server/client API gets even more simple (at the expense of the command class).
I would
put each command into a class of its own, where each class implements a specific interface (e.g. Command)
create a Map<String,Command> which contains a lookup table from each command string to an instance of the class that implements that command
This should help.
Lesson 1: Socket Communications
The TCP connection provides you with one InputStream and one OutputStream. You could just poll the InputStream continuously for the next command (and its inputs) on a dedicated thread. ByteBuffer.wrap(byte[] array) may be useful in interpreting the bytes as chars, ints, longs, etc. You could also pass objects around using serialization.
Any naive approach most likely will not scale well.
Consider using a REST-approach with a suitable small web-server. Jetty is usually a good choice.
To create an listen to a socket, in a very naive way:
mServerSocket = new ServerSocket(port);
listening = true;
while (listening) {
// This call blocks until a connection is made
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
// Here you do your magic, reading and writing what you need from the streams
// You would set listening to true if you have some command to close the server
// remotely
out.close();
in.close();
socket.close();
}
Normally it is a good idea to delegate the processing of the input stream to some other thread, so you can answer the next request. Otherwise, you will answer all requests serially.
You also need to define some kind of protocol of what bytes you expect on the input and output streams, but from your question it looks like you already have one.
You could create an enum with one member per command
interface Comamnd {
// whatever you expect all command to know to perform their function
void perform(Context context);
}
enum Commands implements Command{
ACTIONONE() {
void perform(Context context) {
System.out.println("Action One");
}
},
ACTIONTWO() {
void perform(Context context) {
System.out.println("Action Two");
}
}
}
// initialise
DataInputStream in = new DataInputStream(socket.getInputStream());
// in a loop
byte[] retrievedData= new byte[ITEM_LENGTH];
in.readFully(retrievedData);
String command = new String(retrievedData, 0);
Commands.valueOf(command).perform(context);