For a school project, I have to create a Java Server that is able to service a .NET client that has a Service Reference to a WSDL. I have the .NET Client code:
using (var client = new MathServiceWSDLClient())
{
Console.WriteLine("Multiplying " + Num1 + " and " + Num2 + ": " + client.Multiply(Num1, Num2));
Console.WriteLine("Adding" + Num1 + " and " + Num2 + ": " + client.Add(Num1, Num2));
}
I have also written the Java Server:
Scanner sc = new Scanner(socket.getInputStream());
boolean clientExpectContinue = false;
int contentLength = -1;
String line;
while (!(line = sc.nextLine()).isEmpty()) {
System.out.println(line);
if (line.startsWith("Content-Length")) {
String[] elements = line.split(": ");
contentLength = Integer.parseInt(elements[1]);
} else if (line.startsWith("Expect")) {
clientExpectContinue = true;
}
}
int notEmpties = 0;
byte[] soapEnvelopeData = new byte[contentLength];
char[] soapChars = new char[contentLength];
for (int i = 0; i < contentLength; i++) {
soapChars[i] = (char) socket.getInputStream().read();
if (i == 0)
System.out.println("DFSDFSDf");
}
// System.out.println(socket.getInputStream().read(soapEnvelopeData));
System.out.println(soapEnvelopeData.length);
File file = new File("tempEnvelope.txt");
FileOutputStream fileOut = new FileOutputStream(file);
// fileOut.write(soapEnvelopeData);
System.out.println("Content!");
System.out.println(new String(soapChars));
fileOut.write(new String(soapChars).getBytes());
fileOut.flush();
fileOut.close();
/* Some fancy SOAP and Reflection stuff that works */
The gist of the server is as follows:
It gets the incomming request, reads through the headers and finds the content length. It parses and saves this. From here there are two versions. The first constructs a byte array the same size as the content length, and passes the array as a parameter into the socket.getInputStream().read() method. The second constructs a char array the same length of the content and then reads individual bytes from the stream and casts them to chars.
The issue comes into play when, as shown, I attempt to run the .NET client with multiple requests in one execution. The first request goes off without any sort of discernible issue. When the second one comes in, the server reads the headers, gets the content length and constructs the array. When it comes time to read from the socket, however, the program just waits. Using the char array method, I was able to learn that it waits when reading the first value. Once one minute has expired, .NET times out, and the rest of the program breaks.
If, however, I leave the server running, and only have one request per execution of the .NET client, everything is just fine; the response comes back just as it should.
I have tried some solutions already:
Creating a new MathServiceWSDLClient for every request
Putting every request in its own using() block.
Doing two of the same request at once: two Multiply() or Add() requests.
Any help is appreciated. Thank you all in advance.
~Ryno Janse van Rensburg
.net is probably keeping the socket open for subsequent requests. There may be a bug in your server-like java code related to this.
Are you able to use a framework instead for the Java server code? I would strongly recommend this, and recommend rmbedded Jetty without hesitation. This would mean you wouldn't have to work at the socket level in Java - you can let Jetty handle all of that complication.
Related
I am using the protobuf google implementation for c#.
The story so far..I have a server in c++ and clients in c# and the talk via protobuf messages with TCP.
On the client side, I retrieve the buffers returned from the tcpClient.BeginReceive via the callback provided and append them (so I guess it is cleared from the netstream junk). Then on a worker thread, I try to deserialize the messages.
On the server side the serialization code is:
google::protobuf::uint32 msgSize = msg->ByteSize();
int prefix_length = sizeof(msgSize);
int buffer_length = msgSize + prefix_length;
google::protobuf::uint8 buffer[buffer_length];
google::protobuf::io::ArrayoutputStream array_output(buffer, buffer_length, msgSize);
google::protobuf::io::CodedOutputStream coded_output(&array_output);
coded_output.WriteVarint32(msgSize);
msg->SerializeToCodedStream(&coded_output);
//Send to socket
mSendBuffer.Write(buffer, buffer_length);
On the client I read each chunk using CodedInputStream, read the first number and dispatch the prefix+the msg it contains for deserialization
Figuring out the length:
using (var input = new CodedInputStream(chunk))
{
int len = input.ReadInt32();
int requiredLength = len + input.Position; //(we re sure each time the codedInput starts from the beginning)
byte[] read = await AccumulateResources(requiredLength, chunk);
byte[] msg = new byte[requiredLength];
Buffer.BlockCopy(read, 0, msg , 0 , requiredLength);
Dispatch(msg);
}
Deserialization:
using (var ms = new MemoryStream(buff))
{
ServerMessageFrame msg = null;
try
{
msg = ServerMessageFrame.Parser.ParseDelimitedFrom(ms);
}
catch(Exception e)
{
Logger.Write(conn.clntPrefx + " " + e.ToString());
}
//Use the message
}
The error Messages I receive are:
1)System.InvalidOperationExeption: Wire Type is invalid
2)Protocol message contained invalid tag (zero).
The communication is correct at the beginning and it desyncs at some point, from where it breaks (until I read another msg which starts with a prefixed value aka is not a partial message)
My question is the de/serialization sound or I am missing the mark completely like there is something that I don't account for at all.
SOLVED
The problem was sending the number with double quotes like "40".
So I replaced quotes with empty space and It worked.
This is the code.
HRMID = HRMID.Replace('"', ' ').Trim();
I am trying to call my REST service consecutively but only one of them is working when I do that.
If I call only one of them in one block it works but two of them in one function block is causing problems I think,I don't know why.
Maybe it is something about restriction in the service.
There is no Error just it is not updating the Database.
If I use it alone it works so call is correct.
This is my code , I am waiting for suggestions.
Thanks!
private void GameClosed(object sender, EventArgs e)
{
// Do your stuff when the game closed.
try
{
var client = new WebClient();
var result = client.DownloadString(wsUrl + "/rest/gethrmid/" + UserValues[4]);// Only the first REST API call is working.This one works.
MessageBox.Show("Result is :" + result);
string HRMID = result;
StreamReader SR = new StreamReader("D:/HRMSession.txt");
string hrmValues = SR.ReadToEnd();
client.DownloadString(wsUrl + "/rest/inserthrmsession/" + HRMID + "/" + hrmValues);//This one is not working if i put here.
}
catch (Exception a)
{
MessageBox.Show(a.ToString());
}
}
EDIT:
If I write it as hardcoded it works but if I use the value that is coming from first call it doesn't work.
client.DownloadString(wsUrl + "/rest/inserthrmsession/" + 40 + "/" + hrmValues);//Works.
But I can not convert the value of HRMID to Int because operation contract is string...
I want to read all messages from queue in AWS SQS without deleting them , using C# , but I am only getting the single last message.
Here is the code
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
ReceiveMessageResponse rmrep = sq.ReceiveMessage(rmr);
ReceiveMessageResult rmres = rmrep.ReceiveMessageResult;
//DeleteMessageRequest dmr = new DeleteMessageRequest();
string msgid = "";
string rephandle = "";
XmlDocument xl = new XmlDocument();
for (int i = 0; i < rmres.Message.Count;i++ )
{
rmrep = sq.ReceiveMessage(rmr);
rmres = rmrep.ReceiveMessageResult;
object y = JsonConvert.DeserializeObject<object>(rmres.Message[0].Body);
int z= y.add();
MessageBox.Show(z.ToString());
}
A queue is not a database table; you can't just 'read all the messages'. You tell SQS you want some messages, it picks some and sends them to you; you can't ask it, or expect it, to iterate thru a unique list of messages in the queue and present them to you, it is not intended for that purpose.
If you read 1 or messages, and delete them (or put them in another queue), then eventually you can 'read all the messages', but as long as you don't delete any, its likely that you will keep getting served back some messages multiple times.
You are calling receive message multiple times and thus are not seeing some of your messages. Change your code to something like this:
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
while (true)
{
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
ReceiveMessageResponse response= sq.ReceiveMessage(rmr);
foreach (Message message in response.ReceiveMessageResult.Message)
{
MessageBox.Show(message.ReceiptHandle + ": " + message.Body);
}
}
NOTE: If there are enough messages in the queue (the number depends on the queue and is not documented), you will not be able to receive any more because you will reach your maximum number of in-flight messages.
Another NOTE: If this runs longer than your visibility timeout you will start receiving the same messages again.
I am using a for loop in which Webclient class Downloadstring() method is used to load a external url .
The Url has been provided by SMS service provider in which Mobile number and the message to be transmitted is added.
But message is not being submitted to SMS gateway for all mobile numbers specified in phNos[] array ie downloading Url is skipped for some numbers . This occurs mostly for mobile numbers at end of array.
How can I ensure that program waits until url is loaded for particular number and then the program progresses forward.
WebClient cli = new WebClient();
for (i=0;i<phNos.Length;i++)
{
string url = #"http://example.com?DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
Alternately I have also used System.Net.HttpWebRequest but the problem persist.
for (i=0;i<phNos.Length;i++)
{
string url = #"http://example.com?DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri = new Uri(url);
HttpWebRequest hwb = (HttpWebRequest)HttpWebRequest.Create(targetUri);
System.Net.HttpWebResponse response = hwb1.GetResponse();
int status = (int)response.StatusCode;
if (status == 200)
{
Response.Write("Successfully transmitted" + status);
}
}
Is there any other alternative method to ensure message is submitted 100 %.
Your code looks fine. DownloadString is blocking and if an error occurs it should raise an exception. How does the SMS gateway respond to your request? You should have a look at their documentation, because probably you can write a function that tests whether everything worked fine or not.
const int MAX_RETRY = 10;
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
int cntRetry = 0;
while (!TestResult(cli.DownloadString(url)) && cntRetry < MAX_RETRY)
++cntRetry;
}
The problem could be that you are submitting too many requests to the gateway in a very short time. You could try to put some Thread.Sleep(1000) calls somewhere and see if things get any better.
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
Thread.Sleep(1000);
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
You could also combine the two above examples, using maybe lower values for MAX_RETRY and Thread.Sleep.
const int MAX_RETRY = 5;
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
int cntRetry = 0;
while (!TestResult(cli.DownloadString(url)) && cntRetry < MAX_RETRY) {
Thread.Sleep(500);
++cntRetry;
}
}
I would instantiate a webclient for every call and dispose it after downloadstring is called, like so
foreach(var phone in phNos)
{
using(WebClient cli= new WebClient())
{
url = String.Format(#"http://aaa.bbb.ccc.ddd?DestNo={0}&msg={1}", phone, message);
string result = cli.DownloadString(url);
// check if result has somekind of errorreport maybe?
Trace.WriteLine(result); // optionally write it to a trace file
}
}
Getting it disposed explicitely might help in also closing underlying networkconnections more quickly because I suspect the sheer number of connections are causing the issue. Throttling might also be an option (send less calls to the gateway per minute)
If this are 10000 or 100000 calls the network components between you and the sms gateway can be the culprit. Think off adsl modems/vpn software/routing issues or even the sms-gateway itself.
If that still doesn't resolve the issue: try Fiddler and or Wireshark to deeply inspect http traffic or even tcp/ip traffic.
I am sending a message to multiple phone numbers .
Mobile numbers are stored in an array .
string phNums = "91999999999,9199999998....";.
string[] phNos = phNums.Split(',');
But message doesn't reach all of the recipients , mostly to the numbers that are present near end of array.
The message are sent via a URL provided by SMS service provider in which the phone number and the message is embedded.
for (int i = 0; i < phNos.Length; i++)
{
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri1 = new Uri(url);
System.Net.HttpWebRequest hwb1;
hwb1 = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(targetUri1);
hwb1.GetResponse();
}
As an alternate , I also used Webclient() but still successful message delivery is not guaranteed.
for (int i = 0; i < phNos.Length; i++)
{
WebClient cli= new WebClient();
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
How to ensure that message delivery is not skipped .
Like only if successful response is received on downloading the URL , the loop should progress to next mobile number and so on.
If there is any other possible mechanism , please do suggest. Thanks
I think this is what you want to do:
for (int i = 0; i < phNos.Length; i++)
{
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri1 = new Uri(url);
System.Net.HttpWebRequest hwb1;
hwb1 = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(targetUri1);
System.Net.HttpWebResponse response = hwb1.GetResponse();
if (response != null)
{
int status = (int)response.StatusCode; // this changes the status
// from text response to the
// number, like 404
if (status == 404//or anything else you want to test//)
{
// put your retry logic here, make sure you add a way to break
// so you dont infinitely loop if the service is down or something
}
}
}
URLs have a length constraint. Your are likely hitting this limit and your are losing the trailing phone numbers as a result. Your best bet would be to break your requests into multiple requests of a certain size.
According to the following SO, it may be good practice to limit your request so that the url does not surpass 2000 characters.
What is the maximum length of a URL in different browsers?