问题
Do anyone know if its possible to create a c2dm serverside with C#? How do i add the required parameters (email, password etc)?
回答1:
Here is the core of a basic prototype C# server I created.
class C2DMPrototype
{
// Hardcoded for now
private const string RegistrationId = "XXXXXXXXXXX";
private const string GoogleAuthUrl = "https://www.google.com/accounts/ClientLogin";
// TODO : Production code should use https (secure) push and have the correct certificate
private const string GoogleMessageUrl = "http://android.clients.google.com/c2dm/send";
private const string PostWebRequest = "POST";
private const string AuthTokenHeader = "Auth=";
private const string UpdateClientAuth = "Update-Client-Auth";
// Post data parameters
private const string RegistrationIdParam = "registration_id";
private const string CollapseKeyParam = "collapse_key";
private const string DataPayloadParam = "data.payload";
private const string DelayWhileIdleParam = "delay_while_idle";
private string _authTokenString = String.Empty;
private string _updatedAuthTokenString = String.Empty;
private string _message = String.Empty;
public void StartServer()
{
if ((_authTokenString = GetAuthentificationToken()).Equals(String.Empty))
{
Console.ReadLine();
return;
}
while (true)
{
try
{
Console.Write("Message> ");
_message = Console.ReadLine().ToLower().Trim();
SendMessage(_authTokenString, RegistrationId, _message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
private static string GetAuthentificationToken()
{
string authTokenString = String.Empty;
try
{
WebRequest request = WebRequest.Create(GoogleAuthUrl);
request.Method = PostWebRequest;
NameValueCollection postFieldNameValue = new NameValueCollection();
postFieldNameValue.Add("Email", "XXXXXXXXXXX");
postFieldNameValue.Add("Passwd", "XXXXXXXXXXX");
postFieldNameValue.Add("accountType", "GOOGLE");
postFieldNameValue.Add("source", "Google-cURL-Example");
postFieldNameValue.Add("service", "ac2dm");
string postData = GetPostStringFrom(postFieldNameValue);
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
if (((HttpWebResponse)response).StatusCode.Equals(HttpStatusCode.OK))
{
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
authTokenString = ParseForAuthTokenKey(responseFromServer);
reader.Close();
dataStream.Close();
}
else
{
Console.WriteLine("Response from web service not OK :");
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
}
response.Close();
}
catch (Exception ex)
{
Console.WriteLine("Getting Authentication Failure");
Console.WriteLine(ex.Message);
}
return authTokenString;
}
private static void SendMessage(string authTokenString, string registrationId, string message)
{
//Certeficate was not being accepted for the sercure call
//ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GoogleMessageUrl);
request.Method = PostWebRequest;
request.KeepAlive = false;
NameValueCollection postFieldNameValue = new NameValueCollection();
postFieldNameValue.Add(RegistrationIdParam, registrationId);
postFieldNameValue.Add(CollapseKeyParam, "0");
postFieldNameValue.Add(DelayWhileIdleParam, "0");
postFieldNameValue.Add(DataPayloadParam, message);
string postData = GetPostStringFrom(postFieldNameValue);
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
request.ContentLength = byteArray.Length;
request.Headers.Add(HttpRequestHeader.Authorization, "GoogleLogin auth=" + authTokenString);
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
HttpStatusCode responseCode = ((HttpWebResponse)response).StatusCode;
if (responseCode.Equals(HttpStatusCode.Unauthorized) || responseCode.Equals(HttpStatusCode.Forbidden))
{
Console.WriteLine("Unauthorized - need new token");
}
else if (!responseCode.Equals(HttpStatusCode.OK))
{
Console.WriteLine("Response from web service not OK :");
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
}
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseLine = reader.ReadLine();
reader.Close();
}
private static string GetPostStringFrom(NameValueCollection nameValuePair)
{
StringBuilder postString = new StringBuilder();
for (int i = 0; i < nameValuePair.Count; i++)
{
postString.Append(nameValuePair.GetKey(i));
postString.Append("=");
postString.Append(Uri.EscapeDataString(nameValuePair[i]));
if (i + 1 != nameValuePair.Count)
{
postString.Append("&");
}
}
return postString.ToString();
}
private static string ParseForAuthTokenKey(string webResponse)
{
string tokenKey = String.Empty;
if (webResponse.Contains(AuthTokenHeader))
{
tokenKey = webResponse.Substring(webResponse.IndexOf(AuthTokenHeader) + AuthTokenHeader.Length);
if (tokenKey.Contains(Environment.NewLine))
{
tokenKey.Substring(0, tokenKey.IndexOf(Environment.NewLine));
}
}
return tokenKey.Trim();
}
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// Return "true" to force the certificate to be accepted.
return true;
}
}
回答2:
To answer my own question: yes its possible. I do got some other problems but thats a different story (No auth in c2dm response)
回答3:
Yes, there's a ready made server for this. See source code of C2DM-Sharp at https://github.com/Redth/C2DM-Sharp
来源:https://stackoverflow.com/questions/5714230/c2dm-server-with-c-sharp