Push Notification in Android - Java for Android App Development

Hi,
I wrote an application that gives me the registration id for push notification. I also wrote a server side that sends push notification, but for some reason I am getting id=0:123.... and the notification never sent....
My code is:
void send(string regId)
{
var applicationID = "AIzaSyA-bpa68WzAgRl-ufkhBUAWmg9jTbMZKEo";
var SENDER_ID = "551376547541";
var value = "test";
System.Net.WebRequest tRequest;
tRequest = System.Net.WebRequest.Create("https://android.googleapis.com/gcm/send");
tRequest.Method = "post";
tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", applicationID));
tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));
// string postData = "{ 'registration_id': [ '" + regId + "' ], 'data': {'message': '" + txtMsg.Text + "'}}";
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + regId + "";
Console.WriteLine(postData);
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
tRequest.ContentType = "application/x-www-form-urlencoded";
System.IO.Stream dataStream = tRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
System.Net.WebResponse tResponse = tRequest.GetResponse();
dataStream = tResponse.GetResponseStream();
System.IO.StreamReader tReader = new System.IO.StreamReader(dataStream);
String sResponseFromServer = tReader.ReadToEnd();
lblStat.Text = sResponseFromServer;
tReader.Close();
dataStream.Close();
tResponse.Close();
}
and I am sending:
send("APA91bH4E4zXOHKCMOON3iy85SJbEPlvtuppF4QOyNh88UqjABM3Mddp8B9kgpvXOZdreBHhz6SpjvYmBPwnWJTgApABqKgr9WB2_Lv8kjFRHZGvVMom0k85wEKsS2qfrMNUMaLBxZA5sNrKE7rMHxGVFUlAmLLvqw");
What do I have to do in order to get the notification in my Android ? What this id means ?

I'm sorry but I can't improve your code, but I do know an alternative:
Parse | Push
It's really easy, I found it two days ago and I'm already loving it
Goodluck with your app

Server Side Code
I have used a the below server side code written in PHP to send data to my client device . make sure your device has a google account and firewall protection of anti virus is disabled . Hope this will help . I will advice to use a real device to test the application or you can you bluestacks virtual device
<?php
// Replace with real server API key from Google APIs
$apiKey = "Your API Key";
// Replace with real client registration IDs
$registrationIDs = array( "Your device registration Id");
// Message to be sent
$message = "Test Notification PHP";
// Set POST variables
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registrationIDs,
'data' => array( 'price' => $message )
);
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
//curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields ) );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_POST, true);
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $fields ));
// Execute post
$result = curl_exec($ch);
// Close connection
curl_close($ch);
echo $result;
//print_r($result);
//var_dump($result);
?>

It's unclear from your post which push technology you are using (GCM vs C2DM). Presuming you've opted for GCM (since C2D is deprecated), I've got a working example of both client and server code on Github. I can't post links yet, but it's at github.com/rossja/GCMDemo. Like the prior post, I used PHP for the server side language.
I'm not sure where you're seeing the results you're getting: is that ID contained in the intent extra? Is it something that you're seeing in logcat perhaps?

Please put your code into code tags.

MaartenXDA said:
I'm sorry but I can't improve your code, but I do know an alternative:
Parse | Push
It's really easy, I found it two days ago and I'm already loving it
Goodluck with your app
Click to expand...
Click to collapse
Awesome!I was sick thinking of how to do this and this made it so damn easy!

vijai2011 said:
Awesome!I was sick thinking of how to do this and this made it so damn easy!
Click to expand...
Click to collapse
Yup and you could try the other stuff as well, with the login, users and ParseObjects. It's so easy, I just made a chatroom in 30 minutes .
Sent from my awesome fridge

MaartenXDA said:
Yup and you could try the other stuff as well, with the login, users and ParseObjects. It's so easy, I just made a chatroom in 30 minutes .
Sent from my awesome fridge
Click to expand...
Click to collapse
Chatroom in 30mins? Thats just amazing!

vijai2011 said:
Chatroom in 30mins? Thats just amazing!
Click to expand...
Click to collapse
Yup And you could make something so that the users can send feedback, by just letting them make another ParseObject (e.g "Bugs")

MaartenXDA said:
Yup And you could make something so that the users can send feedback, by just letting them make another ParseObject (e.g "Bugs")
Click to expand...
Click to collapse
Ah...nice .But I have my own code for feedback and reporting fc which sends directly to my mail(along with log for fc) which is better in my case

vijai2011 said:
Ah...nice .But I have my own code for feedback and reporting fc which sends directly to my mail(along with log for fc) which is better in my case
Click to expand...
Click to collapse
Ah yeah that might be better. Although you can also send ParseFiles with Parse

Related

Vista T-Mobile Users Wanted

To test a vista sidebar gadget here.
I've just created this to give a quick overview of how much of the flext balance you have left. I've only tested it with my flext account so have no idea how it will work on other plans. For this to work you'll need to have an account on "My T-Mobile" and be able to view your bill on there.
Anyone who tries this could you please give some feedback on whether it works for you or not?
hi,
i'm a t-mobile user on vista.
are you going to release your source code?
You can view the source of all installed gadgets here:
C:\Users\USERNAME\AppData\Local\Microsoft\Windows Sidebar\Gadgets\
Good tip, i dind't know that (new to vista)
BUT sorry, I'm not the most trusting of people.
And when it comes to installing a gadget to see its code i'd rather now....
especialy the gadget is designed to log into an important and private account of mine...
can you post your source here, and i'll take a look before i install?
[sorry not to trust you.. and if that app works then its a FANTASTIC idea!]
PHP:
/////////////////////////////////////////////////////////////////////
// getData() - Gets the data from CPW via main page
/////////////////////////////////////////////////////////////////////
function getData()
{
XMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
globalURL = "https://www.t-mobile.co.uk/eservice/mtmUserLogin.do?username=" + globalLogon + "&password=" + globalPassword + "&submit=Login"
XMLHttp.onreadystatechange = function()
{
if (XMLHttp.readyState == 4)
{
if (XMLHttp.status == 200)
{
parseData();
}
else
{
document.getElementById("dockedLine1").innerHTML = "Error";
document.getElementById("dockedLine2").innerHTML = "Check";
document.getElementById("dockedLine3").innerHTML = "Settings";
}
}
}
XMLHttp.open("POST", globalURL, true);
//Set the request header so that it's not cached in InternetExplorer
XMLHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
XMLHttp.send(null);
}
function parseData()
{
var Results = XMLHttp.responsetext;
if (Results.match("Please enter a valid username and password"))
{
document.getElementById("dockedLine1").innerHTML = "Wrong Pass";
document.getElementById("dockedLine2").innerHTML = "Or username";
}
else
{
// remaining
subStringFirstPart = Results.indexOf("Remaining:</strong>") + 64;
subStringSecondPart = Results.indexOf("</td>", subStringFirstPart);
remainingbalanace= Results.substring(subStringFirstPart, subStringSecondPart);
// unbilled
subStringFirstPart = Results.indexOf("You have £") + 9;
subStringSecondPart = Results.indexOf("of", subStringFirstPart);
unbilled= Results.substring(subStringFirstPart, subStringSecondPart -1);
// phone number
subStringFirstPart = Results.indexOf("<strong>Mobile number</strong>") + 30;
subStringSecondPart = Results.indexOf("</form>", subStringFirstPart);
phonenumber= Results.substring(subStringFirstPart, subStringSecondPart);
// account number
subStringFirstPart = Results.indexOf("<strong>Account number</strong>") + 31;
subStringSecondPart = Results.indexOf("</form>", subStringFirstPart);
account= Results.substring(subStringFirstPart, subStringSecondPart);
// last bill amount
subStringFirstPart = Results.indexOf("Last Bill") + 63;
subStringSecondPart = Results.indexOf("</td>", subStringFirstPart);
lastbill= Results.substring(subStringFirstPart, subStringSecondPart);
// price plan
subStringFirstPart = Results.indexOf("<strong>Plan</strong>") + 21;
subStringSecondPart = Results.indexOf("</p>", subStringFirstPart);
priceplan= Results.substring(subStringFirstPart, subStringSecondPart);
document.getElementById("dockedLine1").innerHTML = "Allowance: £" + remainingbalanace
document.getElementById("dockedLine2").innerHTML = "Unbilled: " + unbilled
}
and the rest?
there's about 6 or 7 files im not pasting it all here, if you're really that scared don't bother. I'm the biggest gadget developer on the Live Gallery i'm not interested in collecting peoples passwords Ok.
I've looked throught the code and found nothing suspicious to those who may be worried.
I installed it and it works fine, though im not too keen on the colour scheme but thats a minor niggle
Good work!!
Its working fine for me, just told me Im £5 over my allowance - Doh!
Well done,a really useful gadget
Rob
Okay cool, if anyone has any issues please let me know.
aghh, its had a bit of a sh*t fit! (see attatched)
I tried closing the gadget and restarting it and now it sits there for ages saying 'Loading' and then does the same as is in the picture below
edit: I logged onto my t-mobile using IE and then logged off and tried the gadget again, now it's started working again
Did this to me too first time i ran it, but its working now.
Nice app ljames28, Thanks very much.
Works great for me
Not sure on the red colour, T-mob pink or blue maybe?
Great idea! though I am not sure I have ever gone over my £180 flext 35 allowance though
£30 unbilled charges.... damn roaming costs lol
Thanks for taking the time to share it !
When it messes up like it does in that screen shot, that's because it cant get your data for various reasons, maybe you don't have an internet connection or may it couldn't log you in right. In any case try reopening the settings and clicking OK to refresh the gadget.
If anyone wants to make graphics that's fine by me but as you can see they're not my strongpoint!
Edit: New version
With this version i can automatically update it without you having to look on here for updates. Also a bit of error checking and readme link etc
Thanks again. i assume that I simply rename the .zip to .gadget to install it? At least, thats what i had to do
Eh :/ Don't tell me it downloads as .zip? What browser are you using? Are you using a download manager?
ljames28 said:
Eh :/ Don't tell me it downloads as .zip? What browser are you using? Are you using a download manager?
Click to expand...
Click to collapse
Yeah, downloads as a .zip in IE7, no download manager. Don't know why as i can see the file extention isn't a zip when i view the link. No biggy. It's simple enough to rename it.
Thanks again.
How odd, anyone else have this issue? I dont seem to get it.
yeh, .zip here too...gona try it now
Can you make this also for Dutch users (t-mobile Netherlands)

[Q] Linkify vs TextView vs setMovementMethod

hi,
I'm loading a standard HTML code into a text view and would like to see the links to be possible to click and call the browser (web intent)
from all my readings the following code was supposed to work:
Code:
TextView tx = new TextView(this);
tx.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tx.setText(Html.fromHtml(item.get_text()));
tx.setMovementMethod(LinkMovementMethod.getInstance());
mLayout.addView(tx);
but the fact is.. it does not work!
according to google API example link.java
Code:
TextView t3 = (TextView) findViewById(R.id.text3);
t3.setText(
Html.fromHtml(
"<b>text3:</b> Text with a " +
"link " +
"created in the Java source code using HTML."));
t3.setMovementMethod(LinkMovementMethod.getInstance());
it was supposed to be that simple, in it's declaration text3 have no special tags.
I tried several options using Linkify(tx, Lkinkify.ALL); tx.setClickable(true); tx.setLinksClickable(true); setAutoLinkMask(Linkify.ALL) and regardless of what combination I tried I cannot make those HTML links clickable!
important to note that every time I use setMovementMethod the underline on the links disappear from the TextView
any help please??
Have you tried just putting the html from their example in the fromHTML method? It shouldnt be any different but when stuff doesn't work its good to simplify.
Maybe your item.getText is wonky
From something awesome
Just to "close" the post.
at the end I guess was just some mixed binaries floating in my phones flash.. cause after I unistall the app, re-copy the code from the examples and tried it just worked... go figure.
in case anywant fancy.. the final code is:
Code:
TextView tx = new TextView(this);
tx.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tx.setTextColor(getResources().getColor(R.color.txt));
tx.setLinkTextColor(getResources().getColor(R.color.txt));
tx.setMaxWidth((int) (getResources().getDisplayMetrics().density * 360));
tx.setText(Html.fromHtml(item.text));
tx.setMovementMethod(LinkMovementMethod.getInstance());
TextLayout.addView(tx);
if any forum moderator sees this feel free to close the thread.

[SOLVED][Q][Script Help] HttpResponse failing on Motorola Xoom (HC)?

Hey guys, I have an app I'm working on where it will prompt the user for a Name and Email..
When the user hits submit it will then try to collect the data and send it to a PHP script that will then return a JSON array..
I have had this work for so long on Gingerbread Phones (HTC Thunderbolt, Motorola Droid (Milestone), DroidX, Samsung Moment)
However, when I try to use my Motorola Xoom (HoneyComb) for some reason it is getting hung up at HttpResponse..
Code:
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://link.to.my.php.script/");
httppost.setEntity(new UrlEncodedFormEntity(infoValuePairs));
[b]HttpResponse response = httpclient.execute(httppost);[/b] //**Jumps to the catch here!**
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line);
}
is.close();
String result = sb.toString();
JSONArray jArray = new JSONArray(result);
JSONObject json_data = jArray.getJSONObject(0);
sqlName = json_data.getString("name");
sqlEmail = json_data.getString("email");
}
catch(Exception e)
{
setExceptionVerify(e.toString());
}
In the code you can see where I commented where it will jump.. I thought it might have something to do with it being a Wifi-Only Device, but I wasn't sure if there was a special permission for that.. Maybe because android.permissions.INTERNET is only for like 3G/4G etc..
Anyway, here is what I have for permissions in my Manifest file:
Code:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Any help is greatly appreciated guys!
Thanks in advance
Different thread
I had this problem too. Check this link out: <<actually, XDA wont let me post links cuz I'm a new member haha... so just look at the quote below>>
"The network is especially slow and inconsistent, so you should never do network requests on your main thread. In fact, in the upcoming Honeycomb release we’ve made network requests on the main thread a fatal error, unless your app is targeting an API version before Honeycomb. So if you want to get ready for the Honeycomb SDK, make sure you’re never doing network requests on your UI thread. (see “Tips on being smooth” below.)"
Therefore, do all network stuff on a different thread. I would recommend trying an AsyncTask (like the article suggests) and do your network handling there.
<<Sigh.. again, I cant post links >>
Appreciate the input tmpryid..
If you could possibly send me the link in PM that would be awesome.. I knew something was going on and I just wasn't sure..
Thanks again!

[Q] convert existing Android UDP (DatagramPacket) code to TCP

I have existing Android code that submits a pre-constructed packet over UDP to a hardware device... however, I now need to convert this code to work over TCP instead in order to be more reliable. Currently the code will send the packet to the device, and wait for a predetermined Timeout time for the Device to "answer" back over the same UDP port and to the source IP. The hardware device listens on both UDP and TCP on the same port numbers.
The UDP code looks like this:
Code:
serverSocket = new DatagramSocket(ListenPort);
{
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddressOut);
serverSocket.send(sendPacket);
serverSocket.setSoTimeout(TimeOut);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
byte[] tempDataBuf = Arrays.copyOfRange(receiveData, 0, receivePacket.getLength());
MsgReply.ApplyMessageData(tempDataBuf);
System.out.println("RECEIVED: " + MsgReply.toString());
publishProgress(MsgReply.toString().getBytes());
}
Can anyone assist me in converting this code into TCP format?
Appreciate any help!
PS...I asked this question on stackoverflow too, but got no response... heard XDA started a programming forum, so figured I'll give this a bash
Code:
try {
s=new Socket(InetAddress.getByName("192.168.0.2"),2020);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out= new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "ok";
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
//accept server response
String inMsg = null;
try {
inMsg = in.readLine() + System.getProperty("line.separator");
//Send ur data to the below method to do ur process
processdata(inMsg);
}
This my suggestion to use this code under the AsyncTask to support for further higher platform. if didnt done already..
Thank you very much... will give it a try shortly!
jacauc said:
Thank you very much... will give it a try shortly!
Click to expand...
Click to collapse
ok man, if u have problem with this code post it here and send PM.. Then only i can reach U immediately...
I'm particularly interested in how to convert these few particular lines of code to the UDP format..
The attached code sample is very close to what I came up with, but I'm not sure how to construct the packet and parse the results:
Code:
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddressOut);
and
Code:
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
and especially this line:
Code:
byte[] tempDataBuf = Arrays.copyOfRange(receiveData, 0, receivePacket.getLength());
Also...
What does this part do?:
Code:
System.getProperty("line.separator");
Any suggestions?
Thanks again
@jacauc
First of all if u are developing an Client application the following code will help U, For server coding its different its not Like UPD.
UDP probably need both server as all client socket to send and receive the data. But in case of TCP, its not necessary to have a Server Socket only client socket is enough for both read and write..
Code:
java.net.Socket s=new Socket(InetAddress.getByName(pre.getString("ip", "192.168.0.2")),2020);
Click to expand...
Click to collapse
This code create a client tcp socket and allow u to communication to the specific ip and port..
Code:
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddressOut);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
Click to expand...
Click to collapse
these two lines will probably replaced by the above single line..
But if u for handling TCP socket U need two stream one for reading and other for write data to the stream.
Code:
java.io.InputStreamReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
java.io.OutputStreamWriter out= new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
Click to expand...
Click to collapse
The above two line probably help to construct Input and out Stream for u from that Socket.
byte[] tempDataBuf = Arrays.copyOfRange(receiveData, 0, receivePacket.getLength());
Click to expand...
Click to collapse
There is no necessary for this code here because u directly get the String of data from this stream
Code:
String inMsg = in.readLine()
;
Click to expand...
Click to collapse
This line will read the line of string from the stream.
System.getProperty("line.separator");
Click to expand...
Click to collapse
This line is not must. This line will add the system specific line sperator at the end of the string. Is used this in my application to find the line sperator to avoid some system related problem while finding the line end point..
@CoolMonster
Thanks again for your time... this is starting to make a lot of sense now!
I'm getting close!
One thing I had in the UDP code was to send a pre constructed byte to the Digi Wifi XBEE box i'm interfacing with. This is "senddata"
Now if I do
Code:
out.write(sendData);
I get an error message stating that out.write cannot handle a byte.
I have
Code:
private byte[] sendData = new byte[1024];
Does this mean that I should send my data in a string format instead of byte?
@CoolMonster
More information after some additional research:
Prior to sending my string to the hardware module, I need to send some packets to open the communication channel.
For the UDP packet, this is assembled as follows in Hex:
Command ID: 0x02
Command Options: 0
Frame ID: 0x01
Config Options: 0x02
AT Command: 49 53 (This is the HEX for the AT command I want to send, which translates to "IS" in ascii)
Thus, the packet looks like this in Hex:
02 00 01 02 49 53
Then I will get a Hex result which I am already parsing to make sense of the output.
@jacauc
http://stackoverflow.com/a/2879077/1405008
Click to expand...
Click to collapse
hai man check this link for handling byte array in tcp connection...
Let me know if u face problem in handling the above solution..
But I am sure about the Interface what u are using. U better test it by creating simple local server and test the code then test it with the real system..
Appreciate all your help with this! Seems to be working like I wanted it to now.
Thanks
jacauc said:
Appreciate all your help with this! Seems to be working like I wanted it to now.
Thanks
Click to expand...
Click to collapse
Cool, Ur welcome man...

File transfer over TCP sockets

I've been trying to get a simple file transfer between desktop app and phone app. The transfer works up to a point, when it simply ...stops dead.
The server(aka desktop client) enters the listening state, and the phone goes idle.
Anyone has any samples on transfers of large file (bigger than 1 MB)?
mcosmin222 said:
I've been trying to get a simple file transfer between desktop app and phone app. The transfer works up to a point, when it simply ...stops dead.
The server(aka desktop client) enters the listening state, and the phone goes idle.
Anyone has any samples on transfers of large file (bigger than 1 MB)?
Click to expand...
Click to collapse
Have you looked through GoodDayToDie's source code for the File Server? I wonder if he has anything in there that could make that work.
snickler said:
Have you looked through GoodDayToDie's source code for the File Server? I wonder if he has anything in there that could make that work.
Click to expand...
Click to collapse
lalz.
Completely forgot about that one xD
Meh he has it written in C++
Apparently, he didn't do anything that I didn't.
mcosmin222 said:
lalz.
Completely forgot about that one xD
Meh he has it written in C++
Click to expand...
Click to collapse
You can still utilize the transfer portion . I was thinking of seeing what I could do with sockets on the phone. I know it could come in handy somehow
snickler said:
You can still utilize the transfer portion . I was thinking of seeing what I could do with sockets on the phone. I know it could come in handy somehow
Click to expand...
Click to collapse
It's a pain in the ***.
It stops transfer at random points.
mcosmin222 said:
It's a pain in the ***.
It stops transfer at random points.
Click to expand...
Click to collapse
That doesn't surprise me at all for some reason.
Did you double-check your socket multithreading code?
I recently had problems with sockets and it turned out that I had the muti-threading thing wrong.
I think you shouldn't use only one connection and fail if it drops ...
ScRePt said:
Did you double-check your socket multithreading code?
I recently had problems with sockets and it turned out that I had the muti-threading thing wrong.
I think you shouldn't use only one connection and fail if it drops ...
Click to expand...
Click to collapse
What do you mean by socket multthreading code? You mean the use of async methods? or having the thread work on background, using the socket?
Take a look to the Tim Laverty's networking samples.
sensboston said:
Take a look to the Tim Laverty's networking samples.
Click to expand...
Click to collapse
That's what im doing (more or less)
@mcosmin222: The most common reason I saw for why that happened was the thread doing the transfer would crash. There's a lot of things that could cause such a crash, but because it's not the main thread or a UI thread, you don't see it. It just stops. In fact, even the debugger usually doesn't catch it (annoying as hell...)
There are a few common things that non-UI threads aren't allowed to do which you might be trying. For example, attempting to show a MessageBox on a non-UI thread will crash the thread (you can do it by adding a lambda or function to the dispatcher for the UI). In any case, feel free to use or adapt my code, or share yours here and if there's an obvious issue I'll point it out. Incidentally, you can set a larger buffer on the socket if you want the operation to complete without looping.
By the way, the only portion of my webserver that's written in C++ is the file I/O code, which I chose to do in C++ rather than .NET because the phone's stunted .NET framework makes it more difficult than I like to access arbitrary file paths. That code is all fairly clean wrappers around the Win32 calls; I suppose I could comment it more but it's very straightforward to read even if you aren't familiar with managed C++. The actual network code is entirely written in C# 4.5. You could actually simplify it a bit for a direct transfer app, too; I wrote it with a lot of multithreading in case I wanted to re-use the code somewhere that might be expected to have more than one client connecting at a time.
GoodDayToDie said:
@mcosmin222: The most common reason I saw for why that happened was the thread doing the transfer would crash. There's a lot of things that could cause such a crash, but because it's not the main thread or a UI thread, you don't see it. It just stops. In fact, even the debugger usually doesn't catch it (annoying as hell...)
There are a few common things that non-UI threads aren't allowed to do which you might be trying. For example, attempting to show a MessageBox on a non-UI thread will crash the thread (you can do it by adding a lambda or function to the dispatcher for the UI). In any case, feel free to use or adapt my code, or share yours here and if there's an obvious issue I'll point it out. Incidentally, you can set a larger buffer on the socket if you want the operation to complete without looping.
By the way, the only portion of my webserver that's written in C++ is the file I/O code, which I chose to do in C++ rather than .NET because the phone's stunted .NET framework makes it more difficult than I like to access arbitrary file paths. That code is all fairly clean wrappers around the Win32 calls; I suppose I could comment it more but it's very straightforward to read even if you aren't familiar with managed C++. The actual network code is entirely written in C# 4.5. You could actually simplify it a bit for a direct transfer app, too; I wrote it with a lot of multithreading in case I wanted to re-use the code somewhere that might be expected to have more than one client connecting at a time.
Click to expand...
Click to collapse
I am aware that some calls from background threads are not allowed, especially those that have to do with the UI thread.
This is the code for the server. It would seem this one is the problem, somewhere...I just can't see where...
I tried limiting the number of packages sent (that's what the timer is all about).
Code:
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static string[] TransferStages = new string[] { "sendmetadataz-length", "sendmetadataz", "file-length", "file" };
public static int Index = -1;
public static List<string> FilePaths = new List<string>();
public static long CurrentStreamPosition = 0;
public static FileStream ifs;
static int pocketspersecond = 0;
static bool LimitExceded = false;
DispatcherTimer timer = new DispatcherTimer();
public static int CurrentArraySize = 0;
public static int FileIndex = 0;
public AsynchronousSocketListener()
{
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
LimitExceded = false;
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[StateObject.BufferSize];
// Establish the local endpoint for the socket.
// Note: remember to keep the portnumber updated if you change
// it on here, or on the client
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 13001);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.UTF8.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Respond to the client
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
public static void Send(Socket handler, String data)
{
//handler.SendBufferSize = File.ReadAllBytes(@"D:\MUZICA\Activ - Visez.mp3").Length;
// handler.BeginSendFile(@"D:\MUZICA\Activ - Visez.mp3", new AsyncCallback(SendCallback), handler);
#region cotobatura
data = data.Replace("<EOF>", "");
if (data.Contains("sendmetadataz") && data.Contains("length")==false)
{
data = MainWindow.DataContextModel.Files.ElementAt(FileIndex).ToString()+"<EOF>";
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("sendmetadataz-length"))
{
Index++;
if (Index >= MainWindow.DataContextModel.Files.Count)
{
//FileIndex++;
data = "TransfersComplete<EOF>";
}
data = Encoding.UTF8.GetByteCount((MainWindow.DataContextModel.Files.ElementAt(FileIndex).ToString() + "<EOF>").ToString()).ToString();
byte[] MetaDataLength = Encoding.UTF8.GetBytes(data);
handler.SendBufferSize = MetaDataLength.Length;
handler.BeginSend(MetaDataLength, 0, MetaDataLength.Length, 0, new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("file-length"))
{
ifs = File.Open(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location, FileMode.Open);
byte[] gugu = Encoding.UTF8.GetBytes(ifs.Length.ToString());
handler.SendBufferSize = gugu.Length;
handler.BeginSend(gugu, 0, gugu.Length, 0, new AsyncCallback(SendCallback), handler);
}
else if (data.Contains("file") && data.Contains("length") == false)
{
//byte[] filedata = File.ReadAllBytes(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location);
//handler.BeginSend(filedata, 0, filedata.Length, 0,
//new AsyncCallback(SendCallback), handler);
byte[] filedata = new byte[150];
for (int i = 0; i < 150; i++)
{
if (CurrentStreamPosition < ifs.Length)
{
filedata[i] = (byte)ifs.ReadByte();
CurrentStreamPosition++;
CurrentArraySize++;
}
else
{
Array.Resize(ref filedata, CurrentArraySize);
break;
}
CurrentArraySize = 0;
}
// if (pocketspersecond == 25) LimitExceded = true;
//Thread.Sleep(1000);
handler.BeginSend(filedata, 0, filedata.Length, 0, new AsyncCallback(SendCallback), handler);
}
//handler.BeginSendFile(MainWindow.DataContextModel.Files.ElementAt(FileIndex).Location, filedata, null, TransmitFileOptions.ReuseSocket, new AsyncCallback(SendCallback), handler );
// What we want to send back in this application is a game move based on what
// has been received. So we call Play on the GameLogic to give us a move to send back
// data = GameLogic.Play(data);
// Convert the string data to byte data using ASCII encoding.
//byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
//handler.BeginSend(byteData, 0, byteData.Length, 0,
// new AsyncCallback(SendCallback), handler);
#endregion
}
public static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
This is basically modified from the tick tak toe over sockets sample from MSDN.
The only possible call that would affect the UI is the call to the Console, but the code works fine for a while, after it just crashes.
I tried running the whole thing synchronously on the UI thread, the result appears to be the same.
In the Send method, the first 3 stages work (file-legth, metadata, metadata-length) and a few steps in the file stage (which actually sends the file).
AT some point, I assumed the thread was guilty somehow, but I just can't prove it. Running the thing directly on UI thread does not seem to change anything.
If the async method finishes and the socket gets disposed, the thread would "die".
PS: the entire thing is hosted by a WPF application.
Hmm... OK, there are several bugs here. I'm not sure which, if any, are responsible for the problem. I'd be tempted to overuse try-catch-log (for example, on the Send() function) and debug-print statements, but here are some things I can see that could cause a crash or other unexpected failure:
There is no guarantee that "ifs" is instantiated before use. If you for some reason skip the file-length step, the file step will crash with a null pointer exception.
The entire send function is hugely thread-unsafe. For example, if a second request arrives before you're done servicing the first one (which is entirely possible due to where the event gets signaled) then the values of "ifs" and "CurrentStreamPosition" and so on will be unpredictable at any given time. Since CurrentStreamPosition seems to be monotonically increasing, that's probably not going to cause an out-of-bounds exception, but it could cause you to enter a state where the test "if (CurrentStreamPosition < ifs.Length)" always fails.
The line "data = "TransfersComplete<EOF>";" never does anything; the next line (immediately following it) overwrites that variable. If you cared about that string, too bad.
FileIndex never changes; I hope you're only ever sending one file here...
You don't actually check that the number of bytes sent is the number you meant to send (admittedly, it *should* be, but there are cases where it won't be).
The last 150-byte chunk of every file transfer is truncated to the first byte. This is because "CurrentArraySize" is reset to 0 on every iteration of the byte-read loop (why use a byte-read loop?) so whenever "CurrentStreamPosition < ifs.Length" tests false, the "filedata" array will be resized to one byte (or zero if the file is an exact multiple of 150 bytes, which presumeably be correct).
There are probably more, but that's what jumped out at me (well, and some technically correct stylistic issues, like the "... == false" test). Given that your protocol seems to rely on end-of-message flags, I'm guessing that your problem is that since the last part of the file is almost always truncated, that marker is never getting sent. This probably leads to the client concluding that the server will be sending it more data, which it does by sending another "file" request. The server attempts to respond and immedately hits the CurrentStreamPosition < ifs.Length check, fails, goes to the else case, and tries to send a 1-byte packet containing a NULL byte.
Incidentally, does your file transfer protocol really require that the client request each 150-byte chunk one at a time, using a new TCP connection each time? That's... awfully inefficient.
GoodDayToDie said:
Hmm... OK, there are several bugs here. I'm not sure which, if any, are responsible for the problem. I'd be tempted to overuse try-catch-log (for example, on the Send() function) and debug-print statements, but here are some things I can see that could cause a crash or other unexpected failure:
There is no guarantee that "ifs" is instantiated before use. If you for some reason skip the file-length step, the file step will crash with a null pointer exception.
The entire send function is hugely thread-unsafe. For example, if a second request arrives before you're done servicing the first one (which is entirely possible due to where the event gets signaled) then the values of "ifs" and "CurrentStreamPosition" and so on will be unpredictable at any given time. Since CurrentStreamPosition seems to be monotonically increasing, that's probably not going to cause an out-of-bounds exception, but it could cause you to enter a state where the test "if (CurrentStreamPosition < ifs.Length)" always fails.
The line "data = "TransfersComplete<EOF>";" never does anything; the next line (immediately following it) overwrites that variable. If you cared about that string, too bad.
FileIndex never changes; I hope you're only ever sending one file here...
You don't actually check that the number of bytes sent is the number you meant to send (admittedly, it *should* be, but there are cases where it won't be).
The last 150-byte chunk of every file transfer is truncated to the first byte. This is because "CurrentArraySize" is reset to 0 on every iteration of the byte-read loop (why use a byte-read loop?) so whenever "CurrentStreamPosition < ifs.Length" tests false, the "filedata" array will be resized to one byte (or zero if the file is an exact multiple of 150 bytes, which presumeably be correct).
There are probably more, but that's what jumped out at me (well, and some technically correct stylistic issues, like the "... == false" test). Given that your protocol seems to rely on end-of-message flags, I'm guessing that your problem is that since the last part of the file is almost always truncated, that marker is never getting sent. This probably leads to the client concluding that the server will be sending it more data, which it does by sending another "file" request. The server attempts to respond and immedately hits the CurrentStreamPosition < ifs.Length check, fails, goes to the else case, and tries to send a 1-byte packet containing a NULL byte.
Incidentally, does your file transfer protocol really require that the client request each 150-byte chunk one at a time, using a new TCP connection each time? That's... awfully inefficient.
Click to expand...
Click to collapse
I know it is inefficient, but I'm rather new to sockets. I just want it to get working in a "beta stage" then ill optimize it (hance the FileIndex never increasing, the blatant lack of try-catch blocks).
On the client side, once the bytes in the buffer are processed, the server gets another send that to send the following 150 bytes (i use 150 just for the lulz).
So basically, the workfow is as follows:
ask metadata length >server gives the length >client adjusts buffer>ask metadata
ask metdata >server gives metdata>client processes the data>asks file length
ask file length>server gives file length>client adjusts a huge array of bytes in which the file will reside (i know this is horribly inefficient, but at some point i will write directly to a file stream)>asks for the first 150 bytes in the file.
server gets the request, sends 150 bytes to client>client copies the 150 bytes in the array created earlier, the asks for the next 150.
I am using 150 just to make sure the data never splits in more than one buffer.
When the file transfer occurs, a different message is used to signal the end of transfer. Client side counts the bytes it gets, and when it is equal to the file length, it no longer asks 150 bytes.
The whole thing seems to be safe from crashing until it gets to the part where it sends the file. I am aware that in the code i gave you there's some file streams not getting closed, but i've fixed that and the problem still occurs.
Since The debugger won't help me at all, I decided to use a WCF service instead.
mcosmin222 said:
What do you mean by socket multthreading code? You mean the use of async methods? or having the thread work on background, using the socket?
Click to expand...
Click to collapse
I mean worker threads not async.You will always have to have a thread in the background to "accept". once you accept you "read" in a new thread and the parent thread "accepts" again. Accept will freeze the thread.
On the other side, you simply "connect" and "write" in the same thread.
Read and Write is done in a loop via pre-defined buffers syncronously.
But if you want the server to give a response, the above flow is the other way around, and it is then when things get complicated. (server needs to "connect" and client needs to "accept" over a different set of ports and different threads)
Probably if you want to have reliable connection you will need the server to come back with a response "give me more" or sth.
So, trying to assist, it was my guess that drops or stalls could be because the above flow is not implemented properly.
Edit Oh ho, missed a whole new page so I am sorry if the reply is irrelevant now.
I would suggest you use the sync methods of sockets and not callbacks because is super easier to debug. ThreadPool.QueueSth (ctr + space I dont remember how it's called is your friend to handle threads yourself.
And try to separate pure socket handling from domain handling (lengths, metadata, etc). Send some bytes back and forth, clean-up and then move to domain specific things!
Moving the line that resets CurrentArraySize to outside of the for loop may well sove your problem. I'd try that first.
Optimization involves, among other things, removing try blocks. Unoptimized code, when you're trying to just make thigns work, ought to be full of them.
Don't forget that exceptions will not bubble up the call stack across threads. In addition to threads you create yourself, any async callback will happen on a different thread than the one that called the async function. If an uncaught exception occurs, the thread will die. If enough threads die, the program may crash (or at least hang) due to threadpool exhaustion.
GoodDayToDie said:
Moving the line that resets CurrentArraySize to outside of the for loop may well sove your problem. I'd try that first.
Optimization involves, among other things, removing try blocks. Unoptimized code, when you're trying to just make thigns work, ought to be full of them.
Don't forget that exceptions will not bubble up the call stack across threads. In addition to threads you create yourself, any async callback will happen on a different thread than the one that called the async function. If an uncaught exception occurs, the thread will die. If enough threads die, the program may crash (or at least hang) due to threadpool exhaustion.
Click to expand...
Click to collapse
I avoid try-catch in unoptimized code to see where actual exceptions occur (sometime the debugger doesn't break on exception).
Nop still not working.
The thread still appears to be crashing, even wrapped with try catch.
Do you at least know *which* function it's crashing in? Try putting a breakpoint on each function header and then, when one of them is hit, step through the execution until the thread dies. Work backward from there to find the problem.
GoodDayToDie said:
Do you at least know *which* function it's crashing in? Try putting a breakpoint on each function header and then, when one of them is hit, step through the execution until the thread dies. Work backward from there to find the problem.
Click to expand...
Click to collapse
The send function (the one with the case switch) appears to be crashing.
It executes the function then enters the listening stage (does not execute the callback).

Categories

Resources