socket.readLine() reads twice - sockets

i made a client server chat program but for some reason when i send something to the server or vice versa i recieve an additional empty line
for example if the client said "hello"
the server recieves ....
{
client : hello
client :
}
these are send and recieve functions
public static void send(){
out.println(message_out);
}
public void read(){
try {
while(true)
{
message_in = in.readLine();
ConversationBox.append("Client :"+message_in+"\n");
}
} catch (IOException e) {
System.out.println("Client disconnected!");
e.printStackTrace();
}
}
}

The second reading seems to be null value which causes an exception and end of while loop. Instead you should use the following while loop:
while ((message_in = in.readLine()) != null)
ConversationBox.append("Client :"+message_in+"\n");

Your protocol provides no way to uniquely identify the end of a message. If a message is "foo\nbar", you send it as "foo\nbar\n". Since the receiver interpret a newline as a message separator, this will appear to the receive to be two messages, "foo" and then "bar".
If you're going to use a newline as a message separator, you must do one of two things:
Ensure no message ever contains a newline.
If a message contains a newline, escape it somehow and detect that in the receiver.
Otherwise, the message "Hello\n" will be transmitted as "Hello\n\n" and received as "Hello" followed by an empty message.

well thx David Schwartz , i used
if(message_in.isEmpty()){}
else
ConversationBox.append("Server :"+message_in+"\n");
and it's working fine

Related

What is the use of boost::asio::async_write function

Can anyone please help me with this code , what is the use of "boost::asio::async_write" function here
Does it sends acknowledgment back to the client ?
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
It looks like this is from an "echo server" example. async_write writes the contents of boost::asio::buffer(data_, bytes_transferred) to the socket.
Since we're inside handle_read we can guess that this function itself is the completion handler for a likely async_read call that filled that data_ buffer. Since we use the exact number of bytes reported back by async_read (bytes_transferred) and there's no visible manipulation on data_, we can assume that this simply sends the exact message (or data in general) received to socket_. If socket_ was also the endpoint in the async_read this is the definition of an echo server.

Jmeter - Force close a socket/wait until message recieved

I am opening a socket in jmeter (using groovy in JSR223 Sampler), and storing the message in a jmeter variable. This is the below code:
SocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getByName("localhost"),4801);
def server = new ServerSocket()
server.bind(inetSocketAddress)
while(!vars.get("caseId"))) {
server.accept { socket ->
log.info('Someone is connected')
socket.withStreams { input, output ->
InputStreamReader isReader = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isReader);
StringBuffer sb = new StringBuffer();
String str;
while((str = reader.readLine())!= null){
sb.append(str);
}
String finalStr = sb.toString()
String caseId = finalStr.split("<caseId>")[1].split("</caseId>")[0]
vars.put("caseId", caseId)
}
log.info("Connection processed")
}
}
if(vars.get("caseId"))
{
try
{
server.close();
vars.put("socketClose",true);
}
catch(Exception e)
{
log.info("Error in closing the socket: " + e.getMessage());
}
}
Now, there is some time delay between the first loop is executed and the message being recieved from the port. It doesnt receive the message immediately, and hence while loop is executed again. And then message is received and it sets caseId. It goes on to close the socket, because caseId is set. And that is throwing the error, because socket is still waiting for the message. So is there a way, to wait until socket has recieved all the messages, so i could properly close it?
Or just force close the socket, and Jmeter wont throw any exception?
Or when i execute next component, say IF controller in Jmeter, it waits until variable socketClose is set true? In that way, instead of while loops inside JSR223 sampler, i could use multiple If Controllers in Jmeter thread.
This is how ServerSocket.close() function works
public void close()
throws IOException
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
I don't think there is a way "to wait until socket has recieved all the messages" because Socket is dump as a rock and it can either listen for connections or shut down.
Maybe you might be interested in setSoTimeout() function?
Also this line:
vars.put("socketClose",true)
is very suspicious, I think you need to change it either to:
vars.put("socketClose", "true")
or to
vars.putObject("socketClose",true)
as JMeterVariables.put() function can accept only a String, see Top 8 JMeter Java Classes You Should Be Using with Groovy article for more details.

rabbit messaging confirmation

I am using rabbitmq and I want to make sure that if I have a connection problem in the client, the messages that I posted won't be lost. I simulate it with eclipse: I do system.exit the program of fetching after 100 messages. I posted 1000 messages. The second run I don't limit the number of messages and it returns me 840 messages with 3 times. Can you help me?
the code of the producer is:
public void run() {
String json =SimpleQueueServiceSample.getFromList();
while (!(json.equals(""))){
json =SimpleQueueServiceSample.getFromList();
try {
c.basicPublish("", "test",
MessageProperties.PERSISTENT_TEXT_PLAIN, json.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
c.waitForConfirmsOrDie();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
the code of the consumber is:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, true, consumer);
while (true) {
System.out.println(count++);
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
So the challenge for your scenario is how you're handling the acknowledgements.
channel.basicConsume(QUEUE_NAME, true, consumer);
Is the problem. The second parameter of true is the auto-acknowledge field.
To fix that, use:
channel.basicConsume(QUEUE_NAME, false, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//...
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
It looks like you're using RabbitMQ's tutorials, and your code snippet is from part one. If you look at part two, they start talking about acknowledgements and setting up quality of service to provide round-robin dispatch.
It's worth pointing out that the basicConsume() and nextDelivery() combination rely upon a hidden queue that lives within the consumer. So when you call basicConsume() several messages are pulled down to the client to local storage.
The benefit at that approach is that it avoids additional network overhead from calling for each individual message. The problem is that it can put more messages within your local consumer than you wish and you may lose messages if the consumer drops before processing all of the messages in the local hidden queue.
If you truly want your consumers only working on one message a time so that nothing is lost, you probably want to look at the basicGet() method instead of the basicConsume().

Email Fails to send with sms details

The following code listens for an incoming sms, takes all the spaces out of the sms then emails the edited sms. Everything works fine, except that the app fails to send an email. Can anyone see what I am doing wrong and help me?
new Thread() {
public void run() {
try {
DatagramConnection _dc =
(DatagramConnection)Connector.open("sms://");
for(;;) { //'For-Loop' used to listen continously for incoming sms's
Datagram d = _dc.newDatagram(_dc.getMaximumLength());
_dc.receive(d); //The sms is received
byte[] bytes = d.getData();
String address = d.getAddress(); //The address of the sms is put on a string.
String msg = new String(bytes); //The body of the sms is put on a string.
String msg2 = (replaceAll(msg, " ","")) ; //
Store store = Session.getDefaultInstance().getStore();
Folder[] folders = store.list(Folder.SENT);
Folder sentfolder = folders[0]; //Retrieve the sent folder
Message in = new Message(sentfolder);
Address recipients[] = new Address[1];
recipients[0]= new Address("me#yahoo.com", "user");
in.addRecipients(Message.RecipientType.TO, recipients);
in.setSubject("Incoming SMS"); //The subject of the message is added
in.setContent("You have just received an SMS from: " + address + "/n" + "Message: " + msg2); //Here the body of the message is formed
in.setPriority(Message.Priority.HIGH); //The priority of the message is set.
Transport.send(in); //The message is sent
in.setFlag(Message.Flag.OPENED, true);
Folder folder = in.getFolder(); //The message is deleted from the sent folder
folder.deleteMessage(in);
}
}catch (Exception me) { //All Exceptions are caught
}
}
};
public static String replaceAll(String front, String pattern, String back) {
if (front == null)
return "";
StringBuffer sb = new StringBuffer(); //A StringBufffer is created
int idx = -1;
int patIdx = 0;
while ((idx = front.indexOf(pattern, patIdx)) != -1) {
sb.append(front.substring(patIdx, idx));
sb.append(back);
patIdx = idx + pattern.length();
}
sb.append(front.substring(patIdx));
return sb.toString();
}
Thanks
This isn't really an answer to the problem, just an elaboration on my comment above, that might help.
Make sure do something in your exception catch block, so that problems in the code don't go unnoticed. It's possible that your code is not encountering any exceptions, but in order for us to help, we need to try to eliminate potential problems, and since you say the code isn't working, but you have an empty exception handler, that's an easy area to fix first.
the simplest handler is just:
try {
// try sending sms here
} catch (Exception e) {
e.printStackTrace();
}
If you can run this in the debugger (which I highly suggest), then you can now put a breakpoint on the e.printStackTrace() line, and see if it ever gets hit. If it does, inspect the value of e and tell us what it is.
Normally, in my programs, I don't actually use e.printStackTrace() in catch handlers, but I have a logging class that takes strings, and maybe a log level (e.g. info, warning, error, verbose), and writes to a log file. The log file can be attached to emails the users send to tech support, or can be disabled for production if you only want to use the feature while developing.
Anyway, start with a simple printStackTrace() and see if it ever gets hit. Then, report back.
Edit: from the symptoms you describe in the comments after your question, it seems like it's a possibility that
String msg2 = (replaceAll(msg, " ","")) ; //
is throwing an exception, and therefore never letting you get to where you'd send the email. I can't see anything wrong with your implementation of replaceAll() upon initial inspection, but that might be a place to look. Has that implementation been thoroughly unit-tested?
Also, I think you have a "/n" in your code where you probably want a "\n", right?

Android InputStream

I am learning android but I can't get past the InputStream.read().
This is just a socket test - the server sends back two bytes when it receives a connection and I know that this working fine. All I want to do is read these values. The b = data.read reads both values in turn but then hangs, it never returns the -1 value which is what expect it to. Also it does not throw an exception.
Any ideas?
Thanks.
protected void startLongRunningOperation() {
// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
try {
Log.d("Socket", "try connect ");
Socket sock = new Socket("192.168.0.12", 5001);
Log.d("socket", "connected");
InputStream data = sock.getInputStream();
int b = 0;
while (b != -1) {
b = data.read();
}
data.close();
} catch (Exception e) {
Log.d("Socket", e.toString());
}
}
};
t.start();
}
Reaching the end of the stream is a special state. It doesn't happen just because there is nothing left to read. If the stream is still open, but there's nothing to be read, it will "hang" (or block) as you've noticed until a byte comes across.
To do what you want, the server either needs to close/end the stream, or you need to use:
while (data.available() > 0) {
..
When the number of available bytes is zero, there's nothing sitting in the stream buffer to be read.
On the other hand, if you know that there should only ever be two bytes to read, and that's the end of your data, then just read the two bytes and move on (i.e. don't use a while loop). The reason to use a while loop here would only be if you weren't sure how many total bytes to expect.