Socket communication between Java and C# application - java

I have 02 applications, one is written in java and the another one is written in C#. I need to exchange data (Strings) between them thus I use a socket connection.
Currently the C# application acts as server and java application acts as client. The C# application will continuously listen on port "7777" and the Java application will make a socket to "localhost:7777" as start up and use that socket to send data to C# server. I don't close the connection between them since I need to exchange data frequently.
Everything is great until my C# server application sometimes needs to send some Strings to the Java client application. I think about using another port to make my java application becomes a server and the C# application will also become a client. Yet I don't feel that it is a good solution.
P/S: Yes, socket is Bi-direction, in my current application I can send string data from my C# application back to Java application, but only when the Java application first sent a string to the C# application and now it is waiting for the respond data from the C# application.
Thus I want to ask if there is another better solution ? Is it possible if we only use 1 port in total ? Thank you very much.

Your socket works both ways (bi-directional), so you won't need to create another. You can just get the output stream and input stream of the socket, on both sides of the connection, and use those for sending/receiving.
To send a string, the easiest way would probably be to use a DataOutputStream as you can write UTF-8 strings with a simple function.
Java side:
String blah = "hey";
DataOutputStream dataOs = new DataOutputStream(socket.getOutputStream());
dataOs.writeUTF(blah);
The C# side is slightly trickier as you need to account for the fact that the first two bytes sent from the java function writeUTF() will actually be the length (in bytes) of the string that follows. You can grab those 2 bytes first and then throw them into an int, shifting the bits as you go along. Then you can use that int as the size of the buffer when you request the string from the socket. Should look something like this.
C# side:
int length = 0;
byte[] sizeBuffer = new byte[2];
socket.Receive(sizeBuffer);
for (int i = 0; i < sizeBuffer.Length; i += 1)
{
length = length << 8;
length += sizeBuffer[i];
}
byte[] stringBuffer = new byte[length];
socket.Receive(stringBuffer);
string myString = Encoding.UTF8.GetString(stringBuffer, 0, stringBuffer.Length);

Related

Send message through Socket Outputstream from Swift Client to Java Server

As the title says, I'm having some problems connecting my Swift Client to a Java Server by using only native libraries.
Right now I have a Java(client) to Java(server) connection, which works flawlessly, and a Swift(client) to Java(server) connection. My Swift client does connect to the Java server (it shows on the console), but the readFully of my server hangs - the only thing I see is the enormous message length on the console and that's pretty much it.
Swift Code (send):
func send(message: String) {
let data = "msg:\(message)".data(using: .utf8)!
data.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
print("Error joining chat")
return
}
out!.write(pointer, maxLength: data.count)
}
}
Java Server (read):
int lenght = in.readInt();
System.out.println("Message: " + lenght);
if(length>0){
byte[] message = new byte[length];
in.readFully(message), 0, message.length); //This is where the problem is
}
So, basically the Java server hangs on the readFully method. Any ideas why that is? Whether I send a simple String or a Byte array, it always hangs, and for some reason the length is extremely big. Can someone help me understand what I'm doing wrong because I've around this for days and still didn't understand it (still pretty new to Swift).
Thank you very much!
In your Java code, you expect the first 4 bytes to be the length of the message, but in the Swift code, you didn't send the length of the message first. You sent the message itself directly. So now the Java code is left confused as to why the message is shorter than it expected, and waiting for more data to read.
You can try sending the number of bytes in data first:
let byteCountAsByteArray = withUnsafeBytes(of: Int32(data.count).bigEndian, Array.init)
out!.write(byteCountAsByteArray, maxLength: 4)
out!.write(pointer, maxLength: data.count)
I suspect that you are using a DataInputStream in your Java code, hence .bigEndian. But if you are reading this in a little endian way, use .littleEndian instead.

Odd behavior reading SSL socket Java

I am trying to write a simple echo server using SSL. The first line that goes to the server is echoed exactly. When I send a second line, only the first character is echoed. The client works off of a buffered reader's read line from stdin. If I hit CR again the rest of the message comes through. The server seems to be sending all of the data. Here are output from client and server:
CLIENT:
Sending to server at 192.168.0.161
on port 9999
4 seasoNS
echo:4 seasoNS
are really good
echo:a
echo:re really good
SERVER:
server listening on 9999
has cr/lf
4 seasoNS
size to send: 10
has cr/lf
are really good
size to send: 16
exiting...
Here is the client loop:
try {
BufferedReader consoleBufferedReader = getConsoleReader();
sslsocket = getSecSocket(strAddress, port);
BufferedWriter sslBufferedWriter = getSslBufferedWriter(sslsocket);
InputStream srvrStream = sslsocket.getInputStream();
String outMsg;
while ((outMsg = consoleBufferedReader.readLine()) != null) {
byte[] srvrData = new byte[1024];
sslBufferedWriter.write(outMsg);
sslBufferedWriter.newLine();
sslBufferedWriter.flush();
int sz = srvrStream.read(srvrData);
String echoStr = new String(srvrData, 0, sz);
System.out.println("echo:" + echoStr);
}
} catch (Exception exception) {
exception.printStackTrace();
}
This problem seemed so odd that I was hoping there was something obvious that I was missing.
What you're seeing is perfectly normal.
The assumption you're making that you're going to read the whole buffer in one go is wrong:
int sz = srvrStream.read(srvrData);
Instead, you need to keep looping until you get the delimiter of your choice (possibly a new line in your case).
This applies to plain TCP connections as well as SSL/TLS connections in general. This is why application protocols must have delimiters or content length (for example, HTTP has a double new line to end its headers and uses Content-Length or chunked transfer encoding to tell the other party when the entity ends).
In practice, you might not see when your assumption doesn't work for such a small example.
However, the JSSE splits the records it sends into 1/n-1 on purpose to mitigate the BEAST attack. (OpenSSL would send 0/n.)
Hence, the problem is more immediately noticeable in this case.
Again, this is not an SSL/TLS or Java problem, the way to fix this is to treat the input you read as a stream and not to assume the size of buffers you read on one end will match the size of the buffers used to send that data from the other end.

Creating a network packet without using Socket class

I am trying to encode/decode a network packet combining the sender IP address, destination IP address, sender port, destination port and payload data all together.
I've been reading the different ways to do this and everywhere suggests using the Socket class - however, we can't use real network classes like this in our program because it's just a simulated application with no real networking components.
I'm confused on how else I would create a network packet WITHOUT using classes like DatagramPacket or DatagramSocket. The payload data is in byte[] form and the IP addresses are InetAddress. I'm assuming I might have to use some kind of ByteArrayOutputStream to combine all these elements into one network packet of type byte[].
Any suggestions for how I could do this would be really appreciated.
Your use case is confusing. You are creating a networked application but you will never put your application on a network? That makes no sense to me.
In Java the SocketFactory creates Sockets (http://docs.oracle.com/javase/7/docs/api/javax/net/SocketFactory.html). You could implement your own SocketFactory to produce custom subclasses of Socket to create all the non-networky Socket things you need. Without an actual network layer, though, I have no idea how you would get these non-network Sockets to communicate so that you can test stuff like "did the server receive the packet I sent".
Further, I don't think you need an actual Network to do Socket stuff. localhost loopback serves this purpose.
I guess I'm just confused by your question.
i think you just want to create/edit a byte[] or read a byte[]
because a datagram-packet is nothing else than a byte[]!!!
you might think of methods like:
byte[] package; //it sould be at least 20 byte and conform to TCP/IP IPv4
public static byte[] getSourceIp(byte[] package){
byte[] sourceIp = new byte[4];
//System.arraycopy(package, 96, sourceIp, 4); //way shorter
for (int i = 0; i < 4; i ++){
sourceIp [i] = package[i+12]; //12=offset for source ip #ipv4
}
return sourceIp;
}
public static void setSourceIp(byte[] sourceIp , byte[] package){
for (int i = 0; i < 4; i ++){
package[i+12] = sourceIp[i]; //12=offset for source ip #ipv4
}
}
let's assert you byte[] package is conform to the TCP/IP IPv4 protocol and at least 160 bit (20byte) long...
http://en.wikipedia.org/wiki/IPv4
You can use DatagramPacket. It doesn't do anything to the network.
But it seems to me you should be rolling your own packet class here.

Sending data through sockets in java

I am currently working on a one server many clients system. I am trying to get it so the server can send out one command, through a PrintWriter, that will go through to all of the clients connected on that socket. However in practice the command only goes through to one client. All of the clients are created on one socket, and all use the same Scanner. Is what I am trying to do possible?
Some code(incase it helps)
Creation of the socket:
serverSocketRefresh = new ServerSocket(PORTREFRESH);
refresh = serverSocketRefresh.accept();
Creation of the Print Writer and the Scanner:
networkOutputRefresh = new PrintWriter(refresh.getOutputStream(), true);
networkInput = new Scanner(refresh.getInputStream());
Ceation of the clients:
do
{
// Wait for client...
client = serverSocket.accept();
System.out.println("\nNew client accepted.\n");
handler = new ClientHandler(client,networkOutputRefresh, itemArray, bidderArray);
handler.start();
} while (true);
The command im trying to transmit to all of the clients:
public static void updatePrice()
{
networkOutputRefresh.println("1");
}
I am not sure if I correctly understand your code but it seems you are using a single reference of client. And your client reference will be holding the last client reference and hence the printwrite is writing only for that client. Ideally if you want to publish something to all the clients then you should have a collection of client references.Whenever you get an accept on the server socket, add the new client reference to your collection. And whenever you have to publish to all the clients just iterate over your client collection and publish using their associated printwriters.
Why not just use a BufferedReader and BufferedWriter, and make a new one each time you accept a client?
Edit: Or, if that '1' is the only thing you will ever send over that socket, just send it over the socket directly, as a byte. I believe the method is something like socket.write(new byte[] { 1 }, 0, 1), and to read on the other end, socket.read(buffer, 0, 1), where buffer is a byte array of length 1.

A reliable way to read socket data

The application that I am working on has two parts. The server part runs on a Linux machine. The client part, an Android application, queries the server and gets necessary response. Both the parts are written in Java, use socket-based communication, and transfer textual data.
Right after sending the request, here is how the client receives the response:
public static String ReadAvailableTextFromSocket(BufferedReader input) throws IOException {
if (input.ready() == false) {
return null;
}
StringBuilder retVal = new StringBuilder();
while(input.ready()) {
char ch = (char) input.read();
retVal.append(ch);
}
return retVal.toString();
}
However, this doesn't seem to be that reliable. The input is not always ready because of server response time or transmission delays.
Looks like input.ready() is not the right way to wait for getting data.
I am wondering if there is a better way to accomplish this. Perhaps there is some standard practice that I could use.
Perhaps you should use Threads. Keep a listener thread in a while(true) loop that reads more data as it comes in, and simply buffers the data in a data structure (let's say a queue) shared with the main thread. That way, the main thread could simply dequeue data as needed. If the queue is empty, it can infer that no new data was received.
Edit: see this multithreaded chat server/client code as an example.
Here is how I solved this problem. As I am responsible for writing both, the client side as well as the server side, when a request comes to the server, the first line of information I send as the response is the number of bytes the client can expect. This way, the client first waits to read a line. Once the line is read, the client now knows how many bytes of data to expect from the server.
Hope this helps others.
Regards,Peter

Categories

Resources