I have followed Google's tutorial on using Bluetooth on Android. On the server side which is a computer I've used Bluecove.
I have managed to establish the connection between the devices (they weren't paired first and when I ran the program both of the devices asked to accept the pairing). Now I have problem with sending data over the connection. In the Managing a connection section there's a method called write. With that function I'm not able to send anything. It doesn't fail (no errors) but the message doesn't reach the server.
On the server after accepting the connection (acceptAndConnect()) I have the following
DataInputStream inputStream = new DataInputStream(connection.openInputStream());
while(true) {
String input = "";
char c;
while(((c = inputStream.readChar()) > 0) && (c != '\n')) {
input += c;
}
System.out.println("Received: " + input);
}
It doesn't print anything.
The code on the client side is exactly the same as in the tutorial. Where is the problem?
Edit. Actually, if I print c in the server code shown up I get something strange. I've tried to send hello\n. When printing c, I get 桥
汬
漊
After a little bit of more googleing I found Jon Skeet's answer and changed the DataInputStream to an InputStream wrapped in an InputStreamReader and that one in a BufferedReader. Then I can use readLine() and I get the characters right.
Related
These questions may sound silly, but I am new to this networking thing.
I have been trying for quite a few days now to implement a client that works with a Twisted server, but I am failing to get any response back from the server. I have read a lot of docs and watched a few tutorials and I got some of the stuff fixed and got some of the concepts better understood.
Before I step on to asking any questions, I wanna show you my code first. This is what I use to talk to the Twisted-based server:
val socketfactory: SocketFactory = SocketFactory.getDefault()
val socket = socketfactory.createSocket(host, port)
socket.keepAlive = true
socket.tcpNoDelay = true
val isSocketConnected = socket.isConnected //this checks socket's connectivity
val dOut = DataOutputStream(socket.getOutputStream())
val dIn = DataInputStream(socket.getInputStream())
val teststring = "Hi server!"
dOut.writeUTF(teststring)
Log.d("MILESTONE", "MESSAGE SENT AT THIS POINT, Socket is connected ?: $isSocketConnected")
var testreader = ""
while (true) {
testreader = dIn.readUTF()
Log.d("READING:", "RECEIVED THIS: $testreader")
}
My code seems to never get to the second "Log" line. It never gets there. I assume that's because I never get any input from the server. This is getting me confused. Because "socket.isConnected" returns true. Doesn't that mean there is an ongoing connection between the client (me) and the server ? But when I send any output the server doesn't talk back.
So my questions are:
1- Am I doing something wrong? Why do I receive no talk from the server and it blocks the code?
2- Is SocketFactory necessary ?
3- Is there any library that communicates with Twisted from Java ?
Thanks in advance !
For everyone who's struggling to communicate with a Twisted-running python server, I came with the absolutely best solution ever! After inspecting Twisted's open source code, I came to realize it has a "LineReceiver" class that only responds to a message if the line is finished. In other words, you can keep sending data forever and it will never respond until you finish the line and start a new one. Twisted will know the line has finished when a delimiter is used. (It is configured on the server-side). Most servers running Twisted will use a line delimiter : "\r\n"
That's the tricky thing! Once you send that little string, it will start responding to you. Here it is in an example :
val dOut = DataOutputStream(socket.getOutputStream()) //This is my favorite way of sending data!
val dIn = socket.getInputStream().bufferedReader(Charsets.UTF_8) //This is my favorite way of reading data !
val teststring = "hi server! \r\n" //This is the tricky part !
That's it ! all you have to do after that is read the lines from the bufferedReader, like this !
var testreader: List<String>
while (true) {
testreader = dIn.bufferedReader(Charsets.UTF_8).readLines()
for (line in testreader)
Log.e("MILESTONE", line)
}
After I started reading the input, I found out the server started actually sending me strings and communicating back with me. I hope everyone will get their codes working concerning this or any other thing!
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 facing another TCP Socket issue.
I've read through a huge bunch of questions an answers to similar issues, but my problem is somehow different.
I have a Java Client and C++ Server. Everything goes as expected until I'm using different machines (equal to other issues so far)
The messages from the client seem to getting stuck in den TCP Buffer. When I finally close the socket, everything is sent to the server. But these single messages are controlmessages so I need them to be send immediatly. As far as I read this is expected behavior, but how do I send reliable control messages.
Is there a way to force the messages to be sent. (I can leave the socket open for a couple of minutes with nothing is sent.)
Is there something wrong? (see the following code)
Do I have to close the socket each time to perform a REAL flush?
Should I use UDP instead, with an additional amount of protocol work?
Javacode:
mSocketSend = new Socket();
mSocketSend.connect(new InetSocketAddress(mServerIp, mSocketPortSend), mTimeOut);
PrintWriter pw = new PrintWriter(mSocketSend.getOutputStream(), true);
pw.println(data);
C++ Code:
opening socket...(i leave that)
char* buffer = new char[1024];
int rc = recv(mConnectedSocket, buf, 1024, 0);
If you want more of it. Write it. I left almost everything out. ^^ I dont think its relevant. The Communication wents great usually.. No errors at all. So its just this TCPBuffer thingi.
I know there should be some delimiter or message length stuff. But in fact: A message length, which is not sent, does not help. ^^
Thanks for your help.
EDIT #01 The whole bunch of code:
mSocket->createSocketServer(22);
char* buffer = new char[1024];
while(true){
int numberBytes = mSocket->receiveChars(buffer, 1024);
if (numberBytes > 0){
uninterestingHandlingFunction(buffer);
}else{
mSocket->createSocketServer(22);
}
}
bool Socket::createSocketServer(u_short port)
{
if (mConnectedSocket != INVALID_SOCKET)
{
closesocket(mConnectedSocket);
}
if (s == INVALID_SOCKET)
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,0), &wsa) != 0)
return 0;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
return 0;
SOCKADDR_IN addr;
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=ADDR_ANY;
if (bind(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
s = INVALID_SOCKET;
} else if (listen(s, 10) == SOCKET_ERROR)
{
s = INVALID_SOCKET;
}
if (s == INVALID_SOCKET)
{
closesocket(s);
return 0;
}
}
mConnectedSocket = accept(s, NULL, NULL);
if (mConnectedSocket == INVALID_SOCKET)
{
closesocket(s);
return 0;
}
return 1;
}
int Socket::receiveChars(char* buf, unsigned maxSize)
{
if (mConnectedSocket == INVALID_SOCKET)
return -1;
int rc = recv(mConnectedSocket, buf, maxSize, 0);
if (rc == SOCKET_ERROR)
{
std::cout << "Socket: error " << WSAGetLastError() << std::endl;
}
return rc;
}
You wanted it....
EDIT #2 Give it one more try
There are few more things I tried out.
At first: This problem does not occure on a device connected over real network everytime. -> Full Reboot Client&Server -> Problem does not occure -> Full Reboot Client&Server -> Problem occures
Sadly, I don't know what to take from this habit.
Another thing I stumbled over is the bind and listen socket (in Code SOCKET s). This socket listens for connections and if the working thread needs a new connection (on startup or if the previous closes) the socket s gives the next queued connection to mConnectedSocket for recv, other connections are backlogged while one is processed.
From the Java view: a Socket is connected (Device A). next socket (Device B) tries to connect. -> Connection success (its properly controlled in code if this is happens indeed) -> followed by sending data in natural matter. (The socket is still in the backlog on c++ side)
Well, this is hard to transform to the habit I experienced. I'll try to express my thoughts.
Javaside: PrintWriter is created. Feeded with data and is flushed. Because the connection is not fully established (No additional connectedSocket on C++ side). The flush doesn't work. And onClose the socket finally flushes its content.
Please tell me to shut up, if you think so. I dont really know what the "Connection is backlogged" ACTUALLY mean in implementation" ^^
I know, I should open a new thread for each connection, but I can't at the moment. So stick with this server code.
You need to do a flush(), that pushes the data out.
PrintWriter.flush();
Or use a writer with automatic flushing.
You should also make sure that the server reads a line (until \n) and not the full 1024 chars, but I don't know what recv() does so I don't know about that.
Fixed it. Kind of embarassing...
The backlog, i noticed in my edit was indeed the problem.
If two at clients at a time connect to the server, the second is backlogged and his messages would be processed, when the first disconnects.
Additionally (here comes the clue)
As mentioned before its an android java client. There is another thread on java side to receive data from the C++ server. This socket connects on another port.
BUT i set the ports and ip addresses to connect to in a settings activity and there was a bad port for the other socket as default value (same as for the issuesocket, wrong variable taken)
So this socket connects first and the issuesocket connects into the backlog.
This default value is only taken if I enter the settings to set another IPAddress (For example, when I connect to a remote host instead of localhost)
Incredible circumstances... i didnt even wrote the settings...
WIRESHARK would have fixed this.
PrintWriter pw = new PrintWriter(mSocketSend.getOutputStream(), true);
pw.println(data);
pw.flush();
Actually your problem could be on the receiving end, your recv needs to be in a loop (you can google for examples of this). There is no guarantee not much each call to recv will get. If you know you are flushing the data on the Java site, that's probably your problem.
As you are using auto flush and even tried using an explicit flush():
Could be because you don't open the inputStream. Try and do a getInputStream() as well.
Otherwise, Have you tried:
any diff you don't use connect but just give the parameters directly in the Socket constructor?
setTcpNoDelayon the socket (shouldn't cause minutes of delay though!!)?
Your loop is incorrectly coded. Every new recv() will overwrite the previous one. You should advance the offset parameter.
i'm developing a simple test to connect via socket a java server application with an objective-c client side.
This is the java side:
BufferedReader dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = dis.readLine();
System.out.println("Message Received: " + message);
dis.close();
socket.close();
This is the objective-c side:
- (IBAction)click:(id)sender{
#try {
[socket sendString:[NSString stringWithFormat:#"%#",[toSend text]]];
}
#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[toSend resignFirstResponder];
}
There are many problems:
in this way the output of server is:
Message Received: null
i read on this that readLine() needs to receive a string with "\n" that ends string, so i edit the line upon adding \n:
[socket sendString:[NSString stringWithFormat:#"%#\n",[toSend text]]];
but i retrieve an error on this line: EXC_BAD_ACCESS like in screenshot
What could be the problem? can someone help me?
I made a prototype in the Java side, and I don't have Objective-C/iOS or an Apple product.
I suspect the problem could be either in iOS or the Java side. So I hope you're sending text from iOS correctly.
Proposed code:
BufferedReader dis = new BufferedReader(new InputStreamReader(socket.getInputStream(), Charset.defaultCharset()));
The class InputStreamReader need a defined character set. The charset is supposed to be required, not optional! according to Sun documentation.
For expediency, pls just include more code for clean compile next time. Thanks.
Good luck n try it out!
Tommy Kwee
According to your modified post/question, you got an exception from the Objective-C side. So possibly the problem is not on the Java side.
For debugging purposes, I am proposing to make the C code simpler, like...
BOOL success;
success = [socket SendString: #"Hello World!"];
if (success != YES) {
NSLog(#"Fail to send")
}
Notes:
I am not familiar with Objective-C, and I could not find documentation from Apple on it. If you know, please tell me/us.
I did not use code "[toSend text]" because I did not find any references on it.
Other iOS developers are saying "%#" is meant for objects. Is code [toSend text] an object?
Finally, making a socket connection and achieving communication should be possible and not so hard, and eventually we'll get there. So let's do it!
My question is: is there a way to perform a socket OutputStream shutdown or it is not right/fully implemented as it should be by nokia? (J2ME nokia implementation, tested at nokia c6-00 and not closing stream, tested on emulator and works fine)
The main problem is that J2SE server application does not get the end of stream info, the condition read(buffer) == -1 is never true, tries to read from an empty stream and hangs until client is force-killed. This works with a very, very, very ugly workaround on the server side application
Thread.sleep(10);//wait some time for data else you would get stuck........
while ((count = dataInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, count);
if (count != BUFFER_SIZE_1024 || dataInputStream.available() == 0) { //the worlds worst condition ever written... but works
break;
}
Thread.sleep(10);//wait for data input to get some data for dataInputStream.available() to return != 0 if client still sends data else you would not read all data......
}
but this solution is absolutely not acceptable (i dont know something about nokia java coding, i'm missing something, or is it maybe similar to a some sort of nokia-J2ME coding standard and i should get used to it or change platform)
I can't close the client socket after sending data because server sends a response to the client after receiving and processing data.
It looks like this: J2ME client -> J2SE server (hangs on read because client does not perform a outputstream shutdown) -> J2ME
I've tried to:
close the dataOutputStream on the J2ME client - no effect
setSocketOptions (KEEPALIVE, SNDBUF and others) - no effect or errors
nothing seems to work on the target device
sorry but i'm a bit furious right now after this nonsense fight with little java.
I'have searched for the solution but non seems to work
Client code:
SocketConnection socketConnection = (SocketConnection) Connector.open("socket://" + ip + ":" + port);
int count;
byte[] buffer = new byte[BUFFER_SIZE_1024];
// client -> server
DataOutputStream dataOutputStream = new DataOutputStream(socketConnection.openDataOutputStream());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
while ((count = byteArrayInputStream.read(buffer)) != -1) {
dataOutputStream.write(buffer, 0, count);
dataOutputStream.flush();
}
dataOutputStream.close();
byteArrayInputStream.close();
With J2SE, my advice would be to initialize Socket from the java.nio.channels.SocketChannel and just interrupt the blocked thread after reasonable timeout has expired.
I'm not sure which side you are trying to fix, but looks like with J2ME your only option would be to set socket timeout.
EDIT
Actually, now that you've posted client code, I see the problem. If the exception is thrown from the while loop for whatever reason, the output stream is not closed.
Here is my proposed fix for that:
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
try
{
DataOutputStream dataOutputStream = new DataOutputStream(
socketConnection.openDataOutputStream()
);
try
{
while ((count = byteArrayInputStream.read(buffer)) != -1) {
dataOutputStream.write(buffer, 0, count);
dataOutputStream.flush();
}
}
finally
{
dataOutputStream.close();
}
}
finally
{
byteArrayInputStream.close();
}
Note, that it is not strictly necessary to close ByteArrayInputStream, but the code has a habit to mutate, and some day that input stream may become something that needs explicit close.
I've tried the code with the same effect - on the emulator works like a charm, on the device hangs but i solved my problem as follows:
On the J2ME client before sending the 1024 byte packet I'm sending its length and its state (IsNext or IsLast) after this on the J2SE server side in a while(true) loop. I'm reading first the length with a readShort, then state with a readByte (I know it's better to combine it on a one short but I didn't knew if it will work and if the effort was worth it and now when it works I'm not touching this, besides it is easy to add a new state if necessarily and it works quite fast).
After this server goes in to a second nested loop [ while (dataInputStream.available() < length) {} - I'll have to put here a timeout but I'll worry about that later. Also note that on J2ME dataInputStream.available() always returns a 0 (!) so in the J2ME client read in this place is a for (int i = 0; i < length... loop reading a single byte]
When the while(dataInputStream.available() ... loop breaks I'm reading a block of data which length I have, and if the state is IsLast I break the while(true) loop. Works perfectly and stable.
Thanks for the advice and hope this info will help someone