WinPhone推送功能的C语言实现。
直接上源代码:
// wppush.c // 在Linux下编译:gcc -o wppush wppush.c -luuid #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <uuid/uuid.h> int htconnect(char *host, int port) { int white_sock; struct hostent * site; struct sockaddr_in me; site = gethostbyname(host); if (site==NULL) return -2; white_sock = socket(AF_INET,SOCK_STREAM,0); if (white_sock <0) return -1; memset(&me, 0, sizeof(struct sockaddr_in)); memcpy(&me.sin_addr, site-> h_addr_list[0], site-> h_length); me.sin_family = AF_INET; me.sin_port = htons(port); return (connect(white_sock, (struct sockaddr *)&me,sizeof(struct sockaddr)) <0) ? -1 : white_sock; } int htsend(int sock, char *fmt, ...) { char BUF[1024]; va_list argptr; va_start(argptr,fmt); vsprintf(BUF,fmt,argptr); va_end(argptr); printf("\n%s\n",BUF); return send(sock,BUF,strlen(BUF),0); } void uuid2string(const uuid_t uu, char* const str) { int i; for(i=0;i<16;i++) sprintf(str+i*2, "%02X",uu[i]); return; } char * mystrcat(char *dest, char *fmt, ...) { va_list argptr; char buf[1024]; va_start(argptr, fmt); vsprintf(buf, fmt, argptr); va_end(argptr); return strcat(dest, buf); } void wppush1(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip) { int n; uuid_t uu; char guid[200]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 sprintf(buf1, "%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Tile><wp:BackgroundImage></wp:BackgroundImage><wp:Count>", badge, "</wp:Count><wp:Title>qq</wp:Title></wp:Tile></wp:Notification>"); n = strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ",deviceToken," HTTP/1.1",13,10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8",13,10); mystrcat(buf2, "%s%s%c%c", "X-MessageID: ",guid,13,10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 1",13,10); mystrcat(buf2, "%s%c%c", "X-WindowsPhone-Target: token",13,10); mystrcat(buf2, "%s%s%c%c", "Host: ",svrip,13,10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ",n,13,10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue",13,10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); printf("%s\n", buf2); htsend(sock, buf2); return; } void wppush2(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip, int identifier) { int n; uuid_t uu; char guid[200]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 if (0 == type) { sprintf(buf1, "%s%s%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>telephone</wp:Text1><wp:Text2>", alert, "</wp:Text2></wp:Toast></wp:Notification>"); }else if (3 == type) { sprintf(buf1, "%s%s%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>group message</wp:Text1><wp:Text2>", alert,"</wp:Text2><wp:Param>/StartPage.xaml?groupid=", identifier, "</wp:Param></wp:Toast></wp:Notification>"); }else { sprintf(buf1, "%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>message</wp:Text1><wp:Text2>Hi, 有新消息!</wp:Text2><wp:Param>/StartPage.xaml?umid=", identifier, "</wp:Param></wp:Toast></wp:Notification>"); } n = strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ", deviceToken, " HTTP/1.1", 13, 10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8", 13, 10); mystrcat(buf2, "%s%s%c%c", "X-MessageID: ",guid,13,10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 2",13,10); mystrcat(buf2, "%s%c%c", "X-WindowsPhone-Target: toast",13,10); mystrcat(buf2, "%s%s%c%c", "Host: ",svrip,13,10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ",n,13,10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue",13,10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); htsend(sock, buf2); return; } void wppush4(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip, int identifier) { int n; uuid_t uu; time_t timetmp; char guid[200]; char buf[100]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 time(&timetmp); ctime_r(&timetmp, buf); printf("%d, %s\n", timetmp, buf); n = strlen(buf); while('\n' == buf[--n]); buf[n+1] = '\0'; sprintf(buf1, "%s%c%c", "<?xml version=\"1.0\" encoding=\"utf-8\"?>", 13, 10); mystrcat(buf1, "%s%c%c", "<Notification xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"WPNotification\">", 13, 10); mystrcat(buf1, "%s%s%s%c%c", "<Name xmlns=\"\">", alert, ":</Name>", 13, 10); mystrcat(buf1, "%s%d%s%c%c", "<Number xmlns=\"\">", identifier, "</Number>", 13, 10); mystrcat(buf1, "%s%d%s%c%c", "<DateTime xmlns=\"\">", buf, "</DateTime>", 13, 10); mystrcat(buf1, "%s%d%s%c%c", "<Count xmlns=\"\">", badge, "</Count>", 13, 10); mystrcat(buf1, "%s%c%c%s", "<SessionId xmlns=\"\"></SessionId>", 13, 10, "</Notification>"); n = strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ", deviceToken, " HTTP/1.1", 13, 10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8", 13, 10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 4",13,10); mystrcat(buf2, "%s%c%c", "Host: db3.notify.live.net", 13, 10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ",n,13,10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue",13,10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); htsend(sock, buf2); return; } void wppush5(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip) { int n; uuid_t uu; time_t timetmp; char guid[200]; char buf[100]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 sprintf(buf1, "%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\" Version=\"2.0\"> <wp:Tile Template=\"IconicTile\"><wp:WideContent1>message</wp:WideContent1><wp:WideContent2>Hi, 有新消息!</wp:WideContent2><wp:WideContent3> </wp:WideContent3><wp:BackgroundImage></wp:BackgroundImage><wp:Count>", badge, "</wp:Count><wp:BackgroundColor></wp:BackgroundColor></wp:Tile></wp:Notification>"); n = strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ", deviceToken, " HTTP/1.1", 13, 10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8", 13, 10); mystrcat(buf2, "%s%s%c%c", "X-MessageID: ",guid,13,10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 1",13,10); mystrcat(buf2, "%s%c%c", "X-WindowsPhone-Target: token",13,10); mystrcat(buf2, "%s%s%c%c", "Host: ",svrip, 13, 10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ", n, 13, 10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue", 13, 10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); htsend(sock, buf2); return; } void wppush6(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip, int identifier) { int n; uuid_t uu; time_t timetmp; char guid[200]; char buf[100]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 if(0 == type) { sprintf(buf1, "%s%s%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>telephone</wp:Text1><wp:Text2>", alert, "</wp:Text2></wp:Toast></wp:Notification>"); }else if(1 == type) { sprintf(buf1, "%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>message</wp:Text1><wp:Text2>Hi, 有新消息!</wp:Text2><wp:Param>/View/ChatView.xaml?type=1&index=0&id=", identifier, "</wp:Param></wp:Toast></wp:Notification>"); }else if(3 == type) { sprintf(buf1, "%s%d%s%d%s", "<?xml version=\"1.0\" encoding=\"utf-8\"?><wp:Notification xmlns:wp=\"WPNotification\"><wp:Toast><wp:Text1>group message</wp:Text1><wp:Text2>", alert, "</wp:Text2><wp:Param>/StartPage.xaml?groupid=", identifier, "</wp:Param></wp:Toast></wp:Notification>"); }else { return; } n=strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ", deviceToken, " HTTP/1.1", 13, 10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8", 13, 10); mystrcat(buf2, "%s%s%c%c", "X-MessageID: ",guid,13,10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 2",13,10); mystrcat(buf2, "%s%c%c", "X-WindowsPhone-Target: toast",13,10); mystrcat(buf2, "%s%s%c%c", "Host: ",svrip, 13, 10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ", n, 13, 10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue", 13, 10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); htsend(sock, buf2); return; } void wppush7(int sock, char* deviceToken, char* alert, int badge, int type, char* svrip, int identifier) { int n; uuid_t uu; time_t timetmp; char guid[200]; char buf[100]; char buf1[512]; char buf2[1024]; uuid_generate(uu); uuid2string(uu, guid); // 把uuid转成字符串。 time(&timetmp); ctime_r(&timetmp, buf); printf("%d, %s\n", timetmp, buf); n = strlen(buf); while('\n' == buf[--n]); buf[n+1] = '\0'; sprintf(buf1, "%s%c%c", "<?xml version=\"1.0\" encoding=\"utf-8\"?>", 13, 10); mystrcat(buf1, "%s%c%c", "<Notification xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"WPNotification\">", 13, 10); mystrcat(buf1, "%s%s%s%c%c", "<Name xmlns=\"\">", alert, ":</Name>", 13, 10); mystrcat(buf1, "%s%d%s%c%c", "<Number xmlns=\"\">", identifier, "</Number>", 13, 10); mystrcat(buf1, "%s%s%s%c%c", "<DateTime xmlns=\"\">", buf, "</DateTime>", 13, 10); mystrcat(buf1, "%s%d%s%c%c", "<Count xmlns=\"\">", badge, "</Count>", 13, 10); mystrcat(buf1, "%s%s%s%c%c", "<SessionId xmlns=\"\">", alert, "</SessionId>", 13, 10); mystrcat(buf1, "%s%c%c%s", "<Type xmlns=\"\">0</Type>", 13, 10, "</Notification>"); n = strlen(buf1); sprintf(buf2, "%s%s%s%c%c", "POST ", deviceToken, " HTTP/1.1", 13, 10); mystrcat(buf2, "%s%c%c", "Content-Type: text/xml; charset=utf-8", 13, 10); mystrcat(buf2, "%s%c%c", "X-NotificationClass: 4",13,10); mystrcat(buf2, "%s%c%c", "Host: db3.notify.live.net", 13, 10); mystrcat(buf2, "%s%d%c%c", "Content-Length: ", n, 13, 10); mystrcat(buf2, "%s%c%c", "Expect: 100-continue", 13, 10); mystrcat(buf2, "%s%c%c%c%c", "Connection: Keep-Alive",13,10,13,10); strcat(buf2, buf1); htsend(sock, buf2); return; } int main(int argc,char **argv) { int n, socket; char buf[2048]; if (argc<2) { printf( "Please input the hostName. Example:\n %s www.sohu.com\n ",argv[0]); return; } socket = htconnect(argv[1],80); if (socket <1) { printf( "create connecct failed. socket: %d\n", socket); return; } printf("发送推送请求:\n"); wppush6(socket, "http://hk1.notify.live.net/throttledthirdparty/01.00/AQEtF6fm0DuxQLG2iJZViohVAgAAAAADehADAAQUZm52OjJCNUZFOUUyQTMzOUI0RjQFBkxFR0FDWQ","This is message test.", 3, 1, "hk1.notify.live.net", 20056); printf("\n接收推送服务器返回的信息:\n\n"); n = read(socket, buf, sizeof(buf)); buf[n] = '\0'; printf("%s",buf); close(socket); }
执行结果(举例):
# ./wppush hk1.notify.live.net
发送请求开始
... ...
接收推送服务器返回的信息:
HTTP/1.1 200 OK
Cache-Control: private
Server: Microsoft-IIS/7.5
X-DeviceConnectionStatus: Connected
X-NotificationStatus: Received
X-SubscriptionStatus: Active
X-MessageID: b3bc6d8c-179d-4b4c-9642-c1674a86820b
ActivityId: 18bb002b-d2bc-4254-9acf-c4c596dbd14c
X-Server: HK1MPNSM016
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 10 Jan 2012 09:32:39 GMT
Content-Length: 0