最近要做一个手机应用,需要支持多种平台,WM,WP7,Android,iPhone,(MeeGo)etc.
需要和服务器通信,服务器端使用微软的.net实现,因为公司目前的人手几乎都是搞.net的。而手机端的实现就各不相同了……要求的几个功能我发觉跟QQ很像,所以我在标题上写上了“类似QQ”。0,最重要的一点,客户端跨平台,所以集中在协议定制上
1,信息加密,而不是像MSN那样明文传输内容
2,支持登录认证
3,主要是和服务器通信,暂时不考虑客户端对客户端(这点和QQ不太一样)
4,支持文本传输,二进制流传输,较大文件传输等,且效率较高
5,精简,不要引入大规模的库看了下ACE,Boost,发现都太庞大了点,代码也不是很好理解,更重要的,并非所有平台都支持,据说QQ用的是自己的协议,使用TEA加密,所以难度不高的话很想自己实现一套,用RSA/AES之类实现加密等。谁有这方面的经验的,请分享一下,谢谢各位。BTW:希望能得到“经验分享”而不是ctrl+c ctrl+v,如果对我的项目帮助较大,我继续加分。

解决方案 »

  1.   

    号#include <stdio.h>#include <malloc.h> #include <math.h> #include <string.h> #include <ctype.h> #define M 40 /*定义堆栈*/ typedef struct{  double data[M];  int top; }Stack; /*初始化堆栈*/ InitStack(Stack *s) {  s->top=0; } /*判断栈是否为空*/ int StEmpty(Stack *s) {  if(s->top==0)  {    return 1;  }  else  {    return 0;  } } /*入栈操作*/ StPush(Stack *s,double x) {   if(s->top==M)   {    printf("The stack is overflow!");   }   else   {    s->top=s->top+1;    s->data[s->top]=x;   } } /*出栈操作*/ double StPop(Stack *s) {   double t;   if(!StEmpty(s))   {    t=s->data[s->top];    s->top=s->top-1;   }    else   {    printf("StPop:The stack is empty!");    t=NULL;   }   return t; } /*获取栈顶元素*/ double StGetTop(Stack *s) {   double t;   if(!StEmpty(s))   {    t=s->data[s->top];   }   else   {    printf("StGeTop:The stack is empty!");    t=NULL;   }   return t; } /*将数字字符转换成整形*/ int ChrTransferint(char c) {   int n;   switch(c)   {     case '0': n=0;break;     case '1': n=1;break;     case '2': n=2;break;     case '3': n=3;break;     case '4': n=4;break;     case '5': n=5;break;     case '6': n=6;break;     case '7': n=7;break;     case '8': n=8;break;     case '9': n=9;break;   }    return n; } /*获取两个操作符之间数字字符的个数,返回的是最后一个数字字符的位置*/ int GetNumsize(char str[],int n1) {   int n2=n1;   while(isdigit(str[n2])||(str[n2])==46)/*isdigit()判断是否数字字符*/   {    n2=n2+1;   }   return n2; } /*判断上个函数中获得的数字字符串中是否包含小数点,并返回它的位置,不包含,返回-1*/ int IsIncludepoint(char str[],int n1,int n2) {   int n3=-1;   int i;   for(i=n1;i<=n2;i++)   {     if(str[i]=='.')      {        n3=i;        break;      }   }   return n3; } /*将数字字符转换成数值*/ double Transfer(char str[],int n1,int n2,int n3) {  double data=0;  int i,ct;  if(n3<0)  {    for(i=n2;i>=n1;i--)     {       ct=ChrTransferint(str[i]);       data=data+ct*pow(10,n2-i);/*pow(x,y)计算x的y次方的值*/     }  }  else  {     for(i=n3-1;i>=n1;i--)     {       ct=ChrTransferint(str[i]);       data=data+ct*pow(10,n3-1-i);/*pow(x,y)计算x的y次方的值*/     }     for(i=n3+1;i<=n2;i++)     {       ct=ChrTransferint(str[i]);       data=data+ct*pow(0.1,i-n3);/*pow(x,y)计算x的y次方的值*/     }  }  return data; } /*主程序*/ main() {   char str[M],c;   char a;   int n,p1,p2,p3;    /*n为字符串长度,p1,p2,p3分别为数字字符起始位置,结束位置,和小数点位置*/   double data;      /*存放转换后的数值*/   int i=0;   Stack *so=(Stack *)malloc(sizeof(Stack));   /*存储操作符 '(':1,'+':2,'-':3, '*':4,'/':5  字符'),='不压栈*/   Stack *sd=(Stack *)malloc(sizeof(Stack));   /*存储操作数*/   InitStack(so);   InitStack(sd);   printf("Please input formula(format:(1+2)*1.2/4=):\n");   n=0;   while((a=getchar())!='\n')   {     str[n]=a;     n++;   }   while(i<n)    {      char c;      c=str[i];      if(c=='(')       {                                         /*c若是'('直接入栈so,i++*/         StPush(so,1);         i++;       }      else if(isdigit(c))       {         p1=i;                            /*c若是数字字符,一并将后面的连续数字字符转换为数值并压栈到sd,并把i设为后面的*/  p2=GetNumsize(str,p1);  p3=IsIncludepoint(str,p1,p2-1);  /*第一个非数字字符的位置*/  data=Transfer(str,p1,p2-1,p3);         StPush(sd,data);         i=p2;       }      else if(c=='+')        {  StPush(so,2);          /*c若是'+'直接入栈so,i++*/         i++;        }      else if(c=='-')        {         StPush(so,3);          /*c若是'-'直接入栈so,i++*/         i++;        }      else if(c=='*')        {         if(str[i+1]=='(')      /*c若是‘*’它后面的字符是否为'(',若是直接将'*'压栈so,*/           {                              StPush(so,4);            i++;           }         else           {            double t1,t2,t3;       /*若不是,为数字字符,将后面的连续数字字符一并转换成数值t2,sd出栈给t1,将t3=t2*t1压栈到sd*/            t1=StPop(sd);           /*操作符'*'不压栈so*/            p1=i+1;     p2=GetNumsize(str,p1);     p3=IsIncludepoint(str,p1,p2-1);     t2=Transfer(str,p1,p2-1,p3);            t3=t1*t2;            StPush(sd,t3);            i=p2;            }        }      else if(c=='/')        {         if(str[i+1]=='(')           {            StPush(so,5);            i++;           }         else           {            double t1,t2,t3;            t1=StPop(sd);                    /*c是'/'同'*'*/            p1=i+1;     p2=GetNumsize(str,p1);     p3=IsIncludepoint(str,p1,p2-1);     t2=Transfer(str,p1,p2-1,p3);            t3=t1/t2;            StPush(sd,t3);            i=p2;           }        }      else if(c==')')        {         double t1,t2,t3;         int p;         while((p=StPop(so))!=1&&!StEmpty(so))  /*c若是')',出栈so,判断是'+'或'-',出栈sd两个操作数,进行加减运算*/          {                                     /*直到StPop=='('*/            t1=StPop(sd);            t2=StPop(sd);            if(p==2)            {              t3=t2+t1;              StPush(sd,t3);            }            else if(p==3)            {              t3=t2-t1;              StPush(sd,t3);            }          }         if(StGetTop(so)==4)                /*然后判断so栈顶是否为'*'或者'/'*/          {            StPop(so);            t1=StPop(sd);                    /*为'*'出栈so,出栈 sd 获得2个操作数,进行乘法操作*/            t2=StPop(sd);                              t3=t2*t1;            StPush(sd,t3);          }         else if(StGetTop(so)==5)          {            StPop(so);            t1=StPop(sd);         /*为'/'出栈so,出栈 sd 获得2个操作数,进行除法操作*/            t2=StPop(sd);            t3=t2/t1;            StPush(sd,t3);          }          i++;        }      else if(c=='=')        {   double t1,t2,t3;            /*c若是'=',这是so内只有加减号,出栈so到p ,sd到t1,t2*/   int p;          while(!StEmpty(so))           {            t1=StPop(sd);            t2=StPop(sd);     p=StPop(so);            if(p==2)            {              t3=t2+t1;             /*p=='+',加法运算,并将结果t3压栈sd*/              StPush(sd,t3);            }            else if(p==3)            {              t3=t2-t1;       StPush(sd,t3);         /*p=='-',减法运算,并将结果t3压栈sd*/            }    }    i++;        }    } if(!StEmpty(so)||StEmpty(sd)) {   printf("Input error,Back!\n");  /*若so不为空,或者sd为空,且sd中只有一个元素,则输入的式子不对*/ } else {   double end;   int i;                        /*否则,sd中的那个数据就是最后计算结果,打印输出*/   end=StGetTop(sd);   printf("The value of this formula:\n");   for(i=0;i<n;i++)    {      printf("%c",str[i]);    }   printf("%f\n",end); }  getch();}  
      

  2.   

    to fontlose打算做CS架构的,非BS
      

  3.   

    你所说的几个功能需求,我觉得并没有什么技术上难以逾越的障碍。客户端跨平台,这方面的开发思想已经不胜枚举了,基于 .Net 的 SOAP协议就可以借鉴,虽然, SOAP有点繁琐。 
    如果抛开SOAP协议,建议也可以采用HTTP协议,因为ANDROID上已经封装了 apache 的HTTP CLIENT库了,不需要像SOAP那样采用第三方库或者重复开发。你所罗列的几点,支持加密,认证,文本和二进制流传输,实际都已经被HTTP协议实现了。 
    建议LZ就考虑用HTTP协议吧。
      

  4.   

    登录认证, 如果使用HTTP的话,有两个选择
    1. 基于COOKIE的 Credential 验证机制,需要服务器和客户端双方实现。
    2. 基于 WWW-Authenticate 头的BASE64位验证机制,这个只需要服务器方实现,但是因为基于明文传输,不是很建议这种方式。
      

  5.   

    很明显楼主是要用tcp/ip协议来搞,服务器端用.net了,就不要考虑ace和asio了啊,这都是c++的库。
    每个手机端(手机平台)用相应的工具和语言开发。
    协议,完全可以自定义啊。
    lz有过socket开发的经验,这个应该很容易搞定~~~
      

  6.   

    to yinyuanqings
    用soap传输二进制流的话得转码,你认为效率如何?
    apache 的HTTP CLIENT在别的平台下也能用吗?
      

  7.   

    to lincyang
    差不多如你所说,我以前弄过网络游戏通信,但由于是小游戏,扩展性并不怎么好,也没有使用密钥交换,只是用对称加密包装了一下。而QQ这是个不错的东西,感觉。
      

  8.   


    SOAP传输二进制流,然后转码,我现在的公司就在使用这个机制在客户端和服务端交换数据。不过从效率上讲,我觉得不行,现在公司的CRM产品的瓶颈很大一部分程度就是在SOAP的网络IO传输过程上。 当然,未必是算法的效率慢,也有可能是服务器,数据库等等因素的综合结果。事实上,在国外,SOAP已经被认为是一种过于复杂的协议而正在被一些业界反思。见 LinkedIn:
    http://www.linkedin.com/news?actionBar=&articleID=545598811&ids=0OdzkQdzcRd3kIcjAUcz8TdjgRb34OdjsMdzkQdiMNcjwUejkRd3kIczcQd3ATdjgR&aag=true&freq=weekly&trk=eml-tod-b-ttle-4另外 - “apache 的HTTP CLIENT在别的平台下也能用吗”。 是的,只要该平台支持JAVA。
      

  9.   

    还是用标准的即时通信协议吧,这样以后也可以和其他软件兼容。文件传输其实也可以自己定义一套协议啊,这个好像没什么标准的协议,ftp不算。
      

  10.   

    服务器,自己定义协议,使用Dot Net的话是windows的服务器,windows上过去我写过效率最高的I/O完成端口不过不是.Net,基于AIO的,整体负载还行,如果搞分布式的,还是建议上java吧。
      

  11.   

    to yinyuanqings
    谢谢回答,但要用户在他们的手机中部署Java运行环境似乎并不怎么好,我们的程序并不大,必须给用户非常良好的安装和使用体验,我曾经做过Windows Mobile平台上的开发,程序要求用户安装Compact Framwork,结果过半用户都不理解,甚至很多用户因此放弃了我们的程序。to DrSmart
    用.net做服务器是肯定的了,公司只有.net的人手(除了我)。
      

  12.   

    Mmm.... 可能LZ对apache http client有些误解。可能我的表述也不很清楚。 http client 仅仅是针对http客户端协议的一个封装, 有java库上的实现。 它与是不是部署java运行环境,其实没有必然的联系,即使在windows mobile 或者meego系统上,也会有同样的针对http 客户端协议的实现,其工作原理与apache http client应该是一样的 - 因为它们都基于同样的协议。我觉得这个问题的关键之处在于,协议的选取,而不是实现协议的库/运行环境的选取。另一方面,在一开始LZ就强调了,这是一个跨平台的程序,那么就应该做好多种语言开发的准备了。
      

  13.   

    好多天没来,准备结贴了,我还想再问一下yinyuanqings,如果使用http协议的话,一般内容如何封装?比如实现一个简单的用户名/密码登录。
     
      

  14.   

    不是很简单的问题吗,使用tcp/ip协议,设计自己的规约通讯
      

  15.   

    to hnwhh
    我也希望跟你说的那么简单……