yyqf 发表于 2014-2-28 16:22:57

探讨短网址生成原理

关于短网址:

yyqf 发表于 2014-2-28 16:23:32

短网址算法:
    其实短网址的算法跟我们倒没啥关系,因为没有服务器搭建算出来也没用,而且最重要的是这种签名拉~校验拉~算法拉~Hash拉~数学拉什么的。。。正常人是绝对不会感兴趣的。。。。。简而言之,就是通过MD5算法生成签名,然后划分为4段,再进行位运算,再进行字母表索引得到特定字符,最后会生成4个6位字符串,取其中任意一个作为当前短网址。至于重复的问题,首先这个算法算出来以后重复概率应该不高?(咳咳,其实我也不知道高不高,不过每位有26+26+10应该是重复概率很低咯),如果遇到重复的就取另外的字符串嘛,反正先到先得,先映射了的就不用管了。

yyqf 发表于 2014-2-28 16:23:49

短网址接口:
       对于开发者来说,只需要调用接口获得短网址服务器返回的信息就足够了。目前国内的很多门户网站基本都开通了短网址的服务。
      腾讯: url.cn
      网易:126.am
      新浪: t.cn
      人人:rrurl.cn
      百度:dwz.cn
      第一家提供短网址服务的公司: tinyurl.cn
      一般短网址接口的使用方法都是POST参数到服务器,然后服务器返回信息。不过找了下貌似很多都没有开放接口,有的网站开放了接口但是参数里必须要求有用户登陆啊,用户授权神马的。所以还是萌萌的度娘好,完全免费调用,参数干净明朗。而且度娘之前就搞过短网址服务不过由于域名实在太长,被称为网址最长的短网址服务。所以后来悄悄收购了dwz.cn的域名重新低调上线,真是难为度娘了。度娘不哭~~站起来X。
         1、生成短网址
               请求:向dwz.cn/create.php发送post请求,发送数据包括url=长网址
               返回:json格式的数据
                  1、status!=0 出错,查看err_msg获得错误信息(UTF-8编码)
                  2、成功,返回生成的短网址 tinyurl字段         2、自定义短网址
             请求:向dwz.cn/create.php发送post请求,发送数据包括url=长网址&alias=自定义网址
               返回:json格式的数据
                  1、Status!=0 出错,查看err_msg获得错误信息(UTF-8编码)
                  2、成功,返回生成的短网址 tinyurl字段

yyqf 发表于 2014-2-28 16:24:11

HTTP请求:
   一般短网址接口的使用方法都是POST参数到服务器,然后服务器返回信息。不过找了下貌似很多都没有开放接口,有的网站开放了接口请求参数要求用户的授权或登陆。客户端(可以是浏览器,其他应用程序)与服务器进行交互,必须要发送请求,这里用的是HTTP协议。常用的一般是GET请求和POST请求,简单来说两种请求方式基本相同,都是提交数据到服务器。区别在于GET方法是通过URL来提交数据,服务器从收到的URL里解析数据,这样做从安全角度来讲要低一些,而且不能提交大量的数据。POST方法是通过加密的表单方式传送,所以数据量可以比较大且安全。像QQ空间,人人的访问应该就是发送的GET请求,从URL栏就可以直观看到相应的参数如帐号,当前目录是相册还是日志等等,而密码注册一类的都是POST请求。
      就实际代码来看,java的请求比较简单,一些脚本语言也应该比较简单。java里使用封装好的URL,URLCONNECTION可以轻松请求到数据。而VC就特别的麻烦(而且类种类繁多,参数繁多,步骤繁多,总而言之也是个天坑!)。
      1、通过CInternetSession建立会话
      2、准备好各参数,数据报头部,里面包含协议方式,接收编码,请求方式等等
      3、通过CHttpConnection建立连接
      4、通过CHttpFile建立读写文件pfile
      5、 使用pfile来OpenRequest,SendRequest
      6、读取返回数据,关闭连接

      VC是天坑。。。。。还可以用其他API,WINHTTP包,TCP/IP。。。。不过每种都很复杂麻烦而且搅在一堆

yyqf 发表于 2014-2-28 16:24:38

JAVA 在网络方面确实很方便:


view plaincopy

   /*****************************
   * 逸雨清风出品
   * CSDN:http://blog.csdn.net/xyydyyqf
   * DATE: 2013-6-1
   * 祝我儿童节快乐!
   ******************************/
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.acl.Owner;
   
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
   
public class dwz extends JFrame implements ActionListener
{
    private static char[] shortdwz = new char;
    private static char[] line2;
    private static String line;
    private static char[] suitable;
   
    private JPanel panel;
    private JButton btncreat,btnclear,btncopy;
    private JLabel lbllong,lblshort,lblcopy,lblmyshort,lblhelp;
    private JTextField txtlong;
    private JTextField txtshort;
    private JTextField txtmyshort;
   
    public dwz()
    {
      super("短网址生成器");
      panel = new JPanel();
      lbllong = new JLabel("原网址");
      lblshort = new JLabel(" 短网址");
      lblcopy = new JLabel("等待复制");
      lblmyshort = new JLabel("自定义 http://dwz.cn/");
      lblhelp = new JLabel("字母,数字,破折号");
      txtlong = new JTextField(30);
      txtshort = new JTextField(22);
      txtmyshort = new JTextField(14);txtmyshort.setText("");
      txtlong.setHorizontalAlignment(SwingConstants.LEFT);
      txtshort.setHorizontalAlignment(SwingConstants.LEFT); //左对齐
      btncreat = new JButton("生成");
      btnclear = new JButton("清空");
      btncopy = new JButton("复制网址");
      panel.add(lbllong);panel.add(txtlong);
      panel.add(lblmyshort);panel.add(txtmyshort);panel.add(lblhelp);
      panel.add(lblshort);panel.add(txtshort);panel.add(btncopy);
      panel.add(btncreat);panel.add(btnclear);panel.add(lblcopy);
      txtlong.addKeyListener(new KeyEnterLisener());
      txtmyshort.addKeyListener(new KeyEnterLisener());
      btncreat.addActionListener(this);
      btnclear.addActionListener(this);
      btncopy.addActionListener(this);
      this.add(panel);
      this.setSize(400,165);
      this.setLocationRelativeTo(null);
      this.setResizable(false);
    }
    public void actionPerformed(ActionEvent e)
    {
      Object source = e.getSource();
      if (source == btncreat)
      {
      if (txtmyshort.getText().equals(""))
      txtshort.setText(Getdwz(txtlong.getText()));
      else txtshort.setText(GetMydwz(txtlong.getText(),txtmyshort.getText()));
      }
      if (source == btnclear)
      {
      txtshort.setText("");
      txtlong.setText("");
      txtmyshort.setText("");
      lblcopy.setText("等待复制");
      line = null; line2 = null;
      }
      if (source == btncopy)
      {
         Clipboard clipboard = getToolkit().getSystemClipboard(); //获得系统剪切板
         StringSelection stringSelection = new StringSelection(txtshort.getText());
         clipboard.setContents(stringSelection,null);
         lblcopy.setText("复制成功");
      }
    }
    public class KeyEnterLisener extends KeyAdapter
    {
      public void keyPressed(KeyEvent e)
      {
      if (e.getKeyCode() == KeyEvent.VK_ENTER)
          if (txtmyshort.getText().equals(""))
            txtshort.setText(Getdwz(txtlong.getText()));
            else txtshort.setText(GetMydwz(txtlong.getText(),txtmyshort.getText()));
      }
    }
   
    public static String Getdwz(String longwz)
    {
      try {
      String strurl = "url="+longwz;
      URL url = new URL("http://dwz.cn/create.php");//伟大的度娘,无需用户登陆授权就可直接调用API
      //URL url = new URL("http://126.am/api!shorten.action"); 网易的API必须另外要用户的key做参数,其他门户没有找到公开的API
      URLConnection connection = url.openConnection(); //打开url连接
      connection.setDoOutput(true); //设置为输出
      PrintWriter out = new PrintWriter(connection.getOutputStream());
      out.write(strurl); //写入短网址到PORT请求
      out.flush();
      out.close();
      BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      while ((line = in.readLine())!= null) //得到返回的信息
      {
          line2 = line.toCharArray();
      }
      for (int i=0;i<line2.length;i++)
      if (line2 == &#39;h&#39;)
          {
            int k=i,j;
            for (j=0;line2!=&#39;"&#39;;j++)
            {
            if (line2 != &#39;\\&#39;) shortdwz = line2;
            else j--;
            k++;
            }
            suitable = new char;
            for (int temp=0;temp<j;temp++)
            suitable = shortdwz;
            System.out.println(suitable);
            break;
          }
      } catch (Exception e) {
      System.out.println("发送POST请求出现异常!" + e);
      e.printStackTrace();
      }
      if (shortdwz!=&#39;d&#39; || shortdwz!=&#39;w&#39; || shortdwz!=&#39;z&#39;)
      {
      JOptionPane.showMessageDialog(null,"原网址输入错误或无效!","错误",JOptionPane.ERROR_MESSAGE);
      return null;
      }
      line =new String(suitable);
      return line;
    }   
    public static String GetMydwz(String longwz,String myshort)
    {
      try {
      String strmyurl = "url="+longwz+"&alias="+myshort;
      URL url = new URL("http://dwz.cn/create.php");//伟大的度娘,无需用户登陆授权就可直接调用API
      URLConnection connection = url.openConnection(); //打开url连接
      connection.setDoOutput(true); //设置为输出
      PrintWriter out = new PrintWriter(connection.getOutputStream());
      out.write(strmyurl); //写入短网址到PORT请求
      out.flush();
      out.close();
      BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      while ((line = in.readLine())!= null) //得到返回的信息
      {
          line2 = line.toCharArray();
      }
      for (int i=0;i<line2.length;i++)
          if (line2 == &#39;s&#39; && line2 == &#39;t&#39; && line2 == &#39;a&#39; && line2 == &#39;t&#39;)
          {
            JOptionPane.showMessageDialog(null,"哦豁,运气撇,被人捷足先登了\n这个短网址已经被定义过了或不合法,","哦豁",JOptionPane.ERROR_MESSAGE);
            return null;
          }
          else if (line2 == &#39;e&#39; && line2 == &#39;r&#39; && line2 == &#39;r&#39;)
          {
            JOptionPane.showMessageDialog(null,"哦豁,运气撇,被人捷足先登了\n这个长网址已经映射其他短网址了,","哦豁",JOptionPane.ERROR_MESSAGE);
            return null;
          }
      else if (line2 == &#39;h&#39; )
          {
            int k=i,j;
            for (j=0;line2!=&#39;"&#39;;j++)
            {
            if (line2 != &#39;\\&#39;) shortdwz = line2;
            else j--;
            k++;
            }
            shortdwz = &#39;\0&#39;;
            break;
          }
      } catch (Exception e) {
      e.printStackTrace();
      }
      if (shortdwz!=&#39;d&#39; || shortdwz!=&#39;w&#39; || shortdwz!=&#39;z&#39;)
      {
      JOptionPane.showMessageDialog(null,"原网址输入错误或无效!","错误",JOptionPane.ERROR_MESSAGE);
      return null;
      }
      line =new String(shortdwz);
      return line;
    }
   
    public static void main(String[] args) throws Exception
    {
      new dwz().setVisible(true);
    }
}

yyqf 发表于 2014-2-28 16:25:10

VS10一如既往的天坑,尤其是调用系统API的时候:

         //VC发送POST请求的时候始终有异常,暂未处理

view plaincopy

    /*****************************
    * 逸雨清风出品
    * CSDN:http://blog.csdn.net/xyydyyqf
    * DATE: 2013-6-2
    ******************************/
   #include "stdafx.h"
   #include "dwz.h"
   #include "afx.h"
   #include <afxinet.h>
   
   BOOL WINAPI Main_Proc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
   BOOL Main_OnInitDialog(HWND hWnd,HWND hWndFocus,LPARAM lParam);
   void Main_OnCommand(HWND hWnd,int id,HWND hwndCtl,UINT codeNotify);
   void Main_OnClose(HWND hWnd);
   char* Getdwz(CString longwz);
   char* Getmydwz(CString longwz,CString myshortwz);
   
   int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
   {
   DialogBox(hInstance,MAKEINTRESOURCE(IDD_MAINDIALOG),NULL,Main_Proc);
   return 0;
   }
    BOOL WINAPI Main_Proc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
   {
   switch(uMsg)
   {
   //开始消息测试
   HANDLE_MSG(hWnd,WM_INITDIALOG,Main_OnInitDialog);
   HANDLE_MSG(hWnd,WM_COMMAND,Main_OnCommand);
   HANDLE_MSG(hWnd,WM_CLOSE,Main_OnClose);
   //结束消息测试
       }
   return FALSE;
   }
    BOOL Main_OnInitDialog(HWND hWnd,HWND hwndFocus,LPARAM lParam)
   {
   //设置应用程序图标
   HICON hIcon = LoadIcon((HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),MAKEINTRESOURCE(IDI_ICON3));
   SendMessage(hWnd,WM_SETICON,TRUE,(LPARAM)hIcon);
   SendMessage(hWnd,WM_SETICON,FALSE,(LPARAM)hIcon);
   //添加初始化代码
   return TRUE;
   }
   
   //主窗口关闭
void Main_OnClose(HWND hWnd)
   {
   EndDialog(hWnd,0);
   }
   //主窗口命令响应
   void Main_OnCommand(HWND hWnd,int id,HWND hwndCtl,UINT codeNotify)
   {
   switch(id)
   {
   case IDCREAT:
         char *longwz,*myshortwz,*shortwz;
         ZeroMemory(longwz,sizeof(longwz));
         ZeroMemory(myshortwz,sizeof(myshortwz));
         ZeroMemory(shortwz,sizeof(shortwz));
         GetDlgItemText(hWnd,IDC_LONG,longwz,sizeof(longwz));
         GetDlgItemText(hWnd,IDC_MYSHORT,myshortwz,sizeof(myshortwz));
         if (myshortwz == NULL) shortwz = Getdwz(longwz);
         else shortwz = Getmydwz(longwz,myshortwz);
         SetDlgItemText(hWnd,IDC_SHORT,shortwz);
       break;
   case IDCLEAR:
         SetDlgItemText(hWnd,IDC_SHORT,"");
         SetDlgItemText(hWnd,IDC_LONG,"");
         SetDlgItemText(hWnd,IDC_MYSHORT,"");
         break;
   case IDCOPY:
       char* source;
       GetDlgItemText(hWnd,IDC_SHORT,source,sizeof(source));
       if(OpenClipboard(NULL))
       {
         /*HGLOBLA clipbuffer;
         char *buffer;
         EmptyClipboard();
         clipbuffer=GlobalAlloc(GMEM_DDESHARE,source.GetLength()+1);
         buffer=(char *)GlobalLock(clipbuffer);
         strcpy(buffer,LPCSTR(source));
         GlobalUnLock(clipbuffer);
         SetClipboardData(CF_TEXT,clipbuffer);
         CloseClipboard();*/
       }
       break;
   default:break;
   }
   }
   
   char* Getdwz(CString longwz)
   {
   char chHeader;
   char chData;
   char tChars;
   
   memset(tChars,0,128);
   CInternetSession session;
   CHttpConnection* pConnection=NULL;
   CHttpFile* pFile=NULL;
   INTERNET_PORT nPort=8080;
   
   strcpy(chHeader,"Content-Type: application/x-www-form-urlencoded");
   strcpy(chData,"url=");
   strcat(chData,longwz);
   
   pConnection = session.GetHttpConnection("http://dwz.cn",nPort);
   pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,"/create.php");
   pFile->SendRequest(chHeader,(DWORD)strlen(chHeader),(LPVOID *)chData,strlen(chData));
   pFile->Read(tChars,128);
   session.Close();
   
   char* shortdwz;
   ZeroMemory(shortdwz,sizeof(shortdwz));
   for (int i=0;i<sizeof(tChars);i++)
       if (tChars == &#39;h&#39;)
       {
         int k=i,j;
         for (j=0;tChars!=&#39;"&#39;;j++)
         {
         if (tChars != &#39;\\&#39;) shortdwz = tChars;
         else j--;
         k++;
         }
         shortdwz = &#39;\0&#39;;
         break;
       }
   if (shortdwz!=&#39;d&#39; || shortdwz!=&#39;w&#39; || shortdwz!=&#39;z&#39;)
   {
   MessageBox(NULL,"原网址输入错误或无效!","错误",MB_ICONINFORMATION|MB_OK);
   return NULL;
   }
   return shortdwz;   
   }   
   char* Getmydwz(CString longwz,CString myshortwz)
   {
   char chHeader;
   char chData;
   char tChars;
   
   memset(tChars,0,128);
   
   CInternetSession session;
   CHttpConnection* pConnection=NULL;
   CHttpFile* pFile=NULL;
   INTERNET_PORT nPort=8080;
   
   strcpy(chHeader,"Content-Type: application/x-www-form-urlencoded");
   strcpy(chData,"url=");
   strcat(chData,longwz);
   strcat(chData,"&alias=");
   strcat(chData,myshortwz);
   
   pConnection = session.GetHttpConnection("http://dwz.cn",nPort);
   pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,"/create.php");
   pFile->SendRequest(chHeader,(DWORD)strlen(chHeader),(LPVOID *)chData,strlen(chData));
   pFile->Read(tChars,128);
   session.Close();
   
   char* shortdwz;
   ZeroMemory(shortdwz,sizeof(shortdwz));
   for (int i=0;i<sizeof(tChars);i++)
       if (tChars == &#39;s&#39; && tChars == &#39;t&#39; && tChars == &#39;a&#39; && tChars == &#39;t&#39;)
       {
         MessageBox(NULL,"哦豁,运气撇,被人捷足先登了\n这个短网址已经被定义过了或不合法,","哦豁",MB_ICONINFORMATION|MB_OK;
         return NULL;
       }
       else if (tChars == &#39;e&#39; && tChars == &#39;r&#39; && tChars == &#39;r&#39;)
       {
         MessageBox(NULL,"哦豁,运气撇,被人捷足先登了\n这个长网址已经映射其他短网址了,","哦豁",MB_ICONINFORMATION|MB_OK);
         return NULL;
       }
       else if (tChars == &#39;h&#39;)
       {
         int k=i,j;
         for (j=0;tChars!=&#39;"&#39;;j++)
         {
         if (tChars != &#39;\\&#39;) shortdwz = tChars;
         else j--;
         k++;
         }
         shortdwz = &#39;\0&#39;;
         break;
       }
       if (shortdwz!=&#39;d&#39; || shortdwz!=&#39;w&#39; || shortdwz!=&#39;z&#39;)
       {
         MessageBox(NULL,"原网址输入错误或无效!","错误",MB_ICONINFORMATION|MB_OK);
         return NULL;
       }
       return shortdwz;   
   }

saddemon 发表于 2014-3-2 22:37:06

也就是一个base64的正解加反解过程。

8877a 发表于 2014-5-19 16:29:16

谢谢楼主 分享

axlyf 发表于 2018-1-28 12:49:53

学习一下!
页: [1]
查看完整版本: 探讨短网址生成原理