Wednesday, October 31, 2012

china中国cdn服务实战介绍

基本cloud云时代,能多说一些就多说一些吧:

1. webliker(免费+收费)

http://my.webluker.com : 开通需要审核

我于2012-10-31 18点左右注册申请开通pk17s.cn域名加速的账号,19:30分左右收到审核通过邮件.(申请这个这么快,申请那些微博应用怎么那么没效率)

缓存规则界面:

image

设置域名相关信息:

image

如果域名DNS, www.pk17s.cn 未指向http://www.pk17s.cn.xgslb.net/ , 则出现:

错误
您所请求的网址(URL)无法获取

 


然后我给www.pk17s.cn添加两个cname,原cname的优先级10,新的优先级5.


太晚了,先改回去,明天测试


2.CDN联盟(免费+收费)


http://user.wdcdn.com/


后台界面:


image


免费版推送管理页面:


image


价格列表:


image


注册用户送20元,可以买两个月的10元套餐.相当说两个月免费. 未备案的CDN服务器比备案的服务器少(工作人员自己说的). 更高的收费用户我没有使用过.在2012年6月我连续使用两个月.当时CDN服务器有出现挂掉情况.



3. cdnzz.com


https://www.cdnzz.com , 下面是介绍


CDNZZ是一家新兴的云服务CDN加速提供商。目前提供的加速节点有香港和美国。因为有香港的加速节点,所以使用此CDN加速服务,国内访问速度还是不错的,注册后会得到1G的免费月流量,通过邀请好友最多可以增加到10G


服务列表截图:


image

source forge free vhost(自编自译)

1.create project

创建工程

when a create one project on http://pkrssweb.sourceforge.net you will see one vhost in that:

当我创建一个项目http://pkrssweb.sourceforge.net 时,发现了下面一个选项:

image

then,i click admin vhost, it look that:

然后,我点击了 “admin vhost”:

image

i input pkrss.com, because i want to bind this domain only.

我只输入了pkrss.com,因为我现在只想绑定这个域名

2.build environment

建立环境, 这里有中文介绍如何建工程:http://hi.baidu.com/huzhirong/item/c3627aace1b2d6a828ce9d22

see here: https://sourceforge.net/apps/trac/sourceforge/wiki/Custom%20VHOSTs

请看这里: https://sourceforge.net/apps/trac/sourceforge/wiki/Custom%20VHOSTs

 

Virtual Host (VHOST) Configuration

虚拟主机配置

Virtual Hosts (VHOSTs) are a way of supporting many websites using a single pool of web servers. Each project on SourceForge.net is allocated the http://PROJECTNAME.sourceforge.net VHOST for their Project Web site.

虚拟主机向服务器提供许多网站支持的功能.每一个新建的项目都带有一个类似 http://PROJECTNAME.sourceforge.net  的虚拟主机

Some projects elect to register a vanity domain (such as PROJECTNAME.com). Through our Custom VHOST service, project administrators may configure our servers to answer traffic for those domains.

一些项目可以通过我们的VHOST服务来设置绑定您注册的一些顶级域名.

Note: The VHOST facility is not available for the Developer web space.

注意:VHOST单元不适用开发者网站空间.

Step 1: Register the domain

第1步,注册顶级域名

Domain name registration is not typically free; there is an initial cost which registers the domain name for some period of time, then ongoing renewal fees to keep the domain registered. You are responsible for these fees.

域名注册不是免费的.它们需要一些年费注册,如果想继续使用该域名,你需要继续缴纳该年费.

To register a domain, you should contact an ICANN-accredited domain registrar.

联系ICANN认可的域名注册商去注册域名.

If you eventually decide to let your domain lapse, remember to update any links (to avoid the risk of someone else, like a porn website, registering that domain and surprising your users when they try to access information about your project.

如果不再使用该域名.请更新该链接等.不要让一些不法分子继续为害人民.

Step 2: Configure DNS for your domain

第二步 配置您的域名的DNS

In order to have your domain point at some server which answers the traffic, you need to configure DNS (Domain Name Service) for the domain.

为了让服务器正常响应,你需要配置你的域名DNS.

SourceForge.net does not provide DNS services. Many domain registrars provide DNS services on a for-pay basis. There are also several free-to-the-public DNS services, such asGranite Canyon. Your DNS provider will supply documentation on how to use their service. You are responsible for any fees if you choose a for-pay DNS service.

Using the tools provided by your DNS provider, configure the following:

  • yourdomain.com should be a IN A to 216.34.181.97.
  • www.yourdomain.com should be a CNAME to vhost.sourceforge.net.
  • cvs.yourdomain.com should be a CNAME to PROJECTNAME.cvs.sourceforge.net.

image

Step 3: Have us answer your traffic

SourceForge.net servers will not properly route the traffic for your domain until you configure your project's custom VHOSTs. Custom VHOSTs are managed through a self-service tool, which may be accessed as follows:

  1. Login to SourceForge.net as a project administrator and go to the Project Summary page for your project.
  2. Go to the Project Admin pulldown menu.
  3. Click Feature Settings.
  4. Find the Virtual Hosts (VHOSTs) row.
  5. Click the 'Manage' link in the options column.
  6. Enter the domains that you would like us to answer for.
  7. Upload your content to your webspace (you may see 404 errors otherwise)

Records need to be added for each of the hostnames you want our servers to answer. If you want our servers to answer for mydomain.org and www.mydomain.org, you need to add these two records.

VHOST additions become active within six hours of being submitted.

We currently limit the number of custom VHOSTs to ten. Vote for action

how to login with ssh

如何使用ssh登陆

注意:在此后的操作都建立在 Key Agent 基础上,所以 PAGEANT.EXE 不能关闭。如果不关闭,在putty登陆时,不用输入密码,直接登陆;如果关闭,在登陆putty时,需要手动输入自己的密码。
设置putty:
1. Session
host name: shell.sourceforge.netport: 22 ssh
2. Connection->Data
Login detail Auto-login username: user, project-name
3. Connection->SSH
Remote command: create

After that,you login is need some minutes.


这样,登陆时需要几分钟的等待创建shell.


File path description


文件目录说明

[liandl@shell-23008 www]$ cd /home/
frs/ piwik/ scm_hg/ users/
logs-project-web/ project-web/ svn/ wordpress/
logs-user-web/ scm_bzr/ trac/
mediawiki/ scm_git/ user-web/


image

like the picture,i created blog(mount point:wordpress) + trac + piwik + mediawiki…


像这样,我有挂载blog(绑定在wordpress名字) +trac + piwik + mediawiki


bellow is my created projects in these years:


下面是我这几年创建的开源项目:

[liandl@shell-23008 www]$ cd /home/project-web/
error_logs/ pkautoupdate/ pkrssweb/
liandl.u/ pkrss/ pkstock/

bellow is my pkrssweb project wwwroot folder:


下面是我的pkrssweb的wwwroot顶层目录:


[liandl@shell-23008 www]$ cd /home/project-web/pkrssweb/
cgi-bin/ htdocs/


this is look the same as bellow picture in winscp.


这和我们在winscp软件中长的一样.




image

amazon api tool in windows 7

1.download amazon api tool , office doc in here

2.install java.

you can search and download and install java in web.here will not say it.

3.set run environment:

win.bat

setx JAVA_HOME "E:\Program Files\Java"
setx Path %JAVA_HOME%\bin;"%Path%"
setx EC2_HOME "E:\develop\ec2-api-tools"
setx Path "%PATH%";%EC2_HOME%\bin

setx AWS_ACCESS_KEY your apkey
setx AWS_SECRET_KEY your seckey



above, E:\Program Files\Java is my java install folder. e:\develop\ec2-api-tools is my amazon tool unzip folder.


and Shortcuts:


image


4.test it

E:\develop\ec2-api-tools>setx AWS_SECRET_KEY XjpNw7SpqBN9yeJOz2pzjB9u86uoNhOi+L
7APwS

成功: 指定的值已得到保存。
E:\develop\ec2-api-tools>bin\ec2-describe-regions
REGION eu-west-1 ec2.eu-west-1.amazonaws.com
REGION sa-east-1 ec2.sa-east-1.amazonaws.com
REGION us-east-1 ec2.us-east-1.amazonaws.com
REGION ap-northeast-1 ec2.ap-northeast-1.amazonaws.com
REGION us-west-2 ec2.us-west-2.amazonaws.com
REGION us-west-1 ec2.us-west-1.amazonaws.com
REGION ap-southeast-1 ec2.ap-southeast-1.amazonaws.com




Note:

If you get an error that required option -O is missing, check the setting of AWS_ACCESS_KEY, fix any errors, and try the command again.

If you get an error that required option -W is missing, check the setting of AWS_SECRET_KEY, fix any errors, and try the command again.

If you get an error that required option -C is missing, check the setting of EC2_CERT, fix any errors, and try the command again.

If you get an error that required option -K is missing, check the setting of EC2_PRIVATE_KEY, fix any errors, and try the command again.



after that,if i want used us-east-1 endpoint:


E:\develop\ec2-api-tools>setx EC2_URL https://ec2.us-east-1.amazonaws.com


 

image

Tuesday, October 30, 2012

cloudfront中国大陆路由跟踪记录2-Feedback to amazon cloudfront

i feedback to amazon cloudfront’s contract us:

cloudfront in china, access is so slow.
in my months's test,when chinese connect cdn.pkrss.com. the cdn ip is in american or canada. www.pk17s.cn is in west american, but it can quickly than cdn.pkrss.com.

cdn is not Content Delivery Network? or asia endpoint all connect to north america.

after google is not connected well,now bing.
foreign country'
s service is all slow in our country....


these website has one website speed test tool: http://http.7c.com/

my website is http://www.pk17s.cn and my blog http://blog.pkrss.com and my email: liandeliang@yahoo.com.cn. has some one can speed up in china,can contact me.(no waste money)


open the hyperlink,it show that:
Monitoring Hurricane Sandy

We are monitoring Hurricane Sandy and making all possible preparations (e.g. generator fuel, food/water, flashlights, radios, extra staff) in our US East Region. Our infrastructure teams are following our storm response plan that we have developed and utilized during major storms over a multi-year period. Please stay tuned to the Service Health Dashboard for any additional updates.

Customers have also been asking us if there is anything they should be doing at this time related to Hurricane Sandy. Our response to this question is that customers should be following general best practices related to managing highly available deployments (e.g. having a backup strategy, distributing resources across zones).

Are you taking advantage of distributing compute resources across multiple AZs?
How to build fault tolerant applications on AWS?
What can I do to improve my monitoring and watch for unexpected behavior or errors?
What are the storage best practices in EC2?
What should I do if my instance is no longer responding?
How do I troubleshoot instances with Failed Status Checks?
AWS Trusted Advisor - Scan your AWS environment for optimization recommendations



and:

Home > Your Support Cases > Case 74998851
Case 74998851 - cloudfront in china slow

Status Unassigned
Severity Low
By liandeliang@yahoo.com.cn
Opened Oct 30, 2012 02:22 AM PDT
Category General Account Question, Account Management



they ard good work for their country.


but our country?

pkrss-1.1.70

1.add search plugin(this is first origin version)
2.localation some string

jquery plugin-search查找教程

今天我们插件教程的示例目标是:完成一款搜索插件.其包含source源码及文档.

1.搜集资料

1.1 搜集搜索引擎的站内搜索代码

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style type="text/css">
<!--
.normal {font-family: "Verdana","Arial";font-size:14px}
.small {font-family: "Verdana","Arial";font-size:12px}
body { font-family: "Verdana","Arial";font-size:14px}
td {font-family: "Verdana","Arial";font-size:14px}
th {font-family: "Verdana","Arial";font-size:15px}
input {font-family: "Verdana","Arial";font-size:14px}
a {text-decoration:underline; color:blue}
a:link { text-decoration:underline; color: blue }
a:visited { text-decoration:underline; color: blue }
a:hover { text-decoration: underline; color: red }
-->
</style>
<title>My Portal</title>
<script language="javascript">
// 这一段使得FireFox也支持IE的innerText方法
function isIE(){
if (window.navigator.userAgent.toLowerCase().indexOf("msie")>=1)
return true;
else
return false;
}
if(!isIE()){ //firefox innerText define
HTMLElement.prototype.__defineGetter__( "innerText",
function(){
var anyString = "";
var childS = this.childNodes;
for(var i=0; i <childS.length; i++) {
if(childS[i].nodeType==1)
anyString += childS[i].tagName=="BR" ? '\n' : childS[i].innerText;
else if(childS[i].nodeType==3)
anyString += childS[i].nodeValue;
}
return anyString;
}
);
HTMLElement.prototype.__defineSetter__( "innerText",
function(sText){
this.textContent=sText;
}
);
}
// 这一段使得FireFox的HTMLElement具有click方法(add click method to HTMLElement in Mozilla)
try {
// create span element so that HTMLElement is accessible
document.createElement('span');
HTMLElement.prototype.click = function () {
if (typeof this.onclick == 'function')
this.onclick({type: 'click'});
};
}
catch (e) {
// alert('click method for HTMLElement couldn\'t be added');
}
// 对HTMLAnchorElement 加入onclick事件
try {
// create a element so that HTMLAnchorElement is accessible
document.createElement('a');
HTMLElement.prototype.click = function () {
if (typeof this.onclick == 'function') {
if (this.onclick({type: 'click'}) && this.href)
window.open(this.href, this.target? this.target : '_self');
}
else if (this.href)
window.open(this.href, this.target? this.target : '_self');
};
}
catch (e) {
// alert('click method for HTMLAnchorElement couldn\'t be added');
}
// 跟踪回车键事件
function captureKeys (evt) {
var keyCode = evt.keyCode ? evt.keyCode :
evt.charCode ? evt.charCode : evt.which;
if (keyCode == 13) {
// cancel key:
if (evt.preventDefault) {
evt.preventDefault();
}
var dq = getCookie('default-engine');
if( dq == null) dq = "baidu_txt";
submit_query( dq );
return false;
}
return true;
}
// cookie 功能函数
function getCookie(cookieName)
{
var cookieString = document.cookie;
var start =cookieString.indexOf(cookieName+'=');
if(start == -1)
return null;
start += cookieName.length + 1;
var end = cookieString.indexOf(';', start);
if(end == -1)
return unescape(cookieString.substring(start));
return unescape(cookieString.substring(start,end));
}
function setCookie(cookieName, cookieValue)
{
var expires = new Date();
expires.setTime( expires.getTime() + 3*30*24*60*60*1000); // 3 months
document.cookie = cookieName + '=' + escape(cookieValue)+';expires='+expires.toGMTString();
}
function removeCookie(cookieName)
{
var expires = new Date();
expires.setTime( expires.getTime() - 1);
document.cookie = cookieName + '=fooxxx;expires='+expires.toGMTString();
}
function $(id) {
return document.getElementById(id);
}
// 调式Object用,适用于IE,Firefox下可用firebug
function dumpObject(obj)
{
var temp="";
for (x in obj)
temp += x + ": " + obj[x] + "\n";
var popup = window.createPopup();
popup.document.body.innerHTML = '<textarea rows=30 cols=40>' + temp + '</textarea>';
popup.show(100, 100, 300, 400, document.body);
}
// 多种查询引擎请求分派
function submit_query(t_query)
{
var keyword = document.getElementById("keyword");
var mylink = document.getElementById("mylink");
var loc = "";
switch(t_query)
{
case "baidu_txt":
loc = "http://www.baidu.com/s?wd=" + keyword.value;
break;
case "baidu_img":
loc = "http://image.baidu.com/i?ct=201326592&lm=-1&tn=baiduimagenojs&pv=&word=" + keyword.value + "&z=0&pn=0&rn=16&cl=2";
break;
case "yodao_txt":
loc = "http://www.yodao.com/search?q=" + encodeURI(keyword.value) + "&ue=utf8&keyfrom=web.index";
break;
case "yodao_img":
loc = "http://image.yodao.com/search?q=" + encodeURI(keyword.value) + "&ue=utf8&keyfrom=image.index";
break;
case "yodao_dict":
loc = "http://dict.yodao.com/search?q=" + encodeURI(keyword.value) + "&ue=utf8&keyfrom=dict.index";
break;
case "yodao_blog":
loc = "http://blog.yodao.com/search?q=" + encodeURI(keyword.value) + "&ue=utf8&keyfrom=blog.top";
break;
case "iask_ditu":
loc = "http://ditu.iask.com/a/r.php?cl=北京&key=" + keyword.value;
break;
case "verycd":
loc = "http://www.verycd.com/search/folders/" + encodeURI(keyword.value);
break;
case "google_txt":
loc = encodeURI("http://www.google.com/search?hl=en&q=" + keyword.value +"&btnG=Google+Search");
break;
case "yahoo_txt":
loc = "http://search.yahoo.com/search?p="+encodeURI(keyword.value)+"&vc=&fr=yfp-t-501&toggle=1&cop=mss&ei=UTF-8&fp_ip=CN";
break;
case "trans_en":
loc = "http://209.85.171.104/translate_c?hl=en&sl=en&tl=zh-CN&u=http://" + keyword.value + "/&usg=ALkJrhijPevZUxPtrHDj94k1U9Wo8x7S8g";
break;
case "google_code":
loc = "http://www.google.com/codesearch?q=" + keyword.value + "&hl=en&btnG=Search+Code";
break;
case "google_scholar":
loc = "http://scholar.google.com/scholar?q=" + keyword.value + "&hl=en&lr=&btnG=Search";
break;
}
setEngine(t_query);
setCookie('default-engine', t_query);
mylink.href= loc;
mylink.click();
}
function getDefaultEngine()
{
var dq = getCookie('default-engine');
if( dq == null) dq = "baidu_txt";
return dq;
}
function setDefaultEngine()
{
var old_e = getDefaultEngine();
if( $(old_e).innerText.indexOf('*') < 0)
$(old_e).innerText = $(old_e).innerText + '*';
}
function setEngine( new_e )
{
var old_e = getDefaultEngine();
if( $(old_e).innerText.indexOf('*') >= 0)
$(old_e).innerText = $(old_e).innerText.replace('*','');
if( $(new_e).innerText.indexOf('*') < 0)
$(new_e).innerText = $(new_e).innerText + '*';
setCookie('default-engine', new_e);
}
</script>
</head>
<body onload='setDefaultEngine()'>
<table border="0" width="100%">
<tr><td>
<a href="http://www.google.com" id="mylink" target="_blank">Search:</a>
<input type="text" name="keyword" size="20" id="keyword" onkeypress="return captureKeys(event);">
<a href="javascript:;" id='baidu_txt' onclick="submit_query('baidu_txt')">百度</a>
<a href="javascript:;" id='google_txt' onclick="submit_query('google_txt')">Google</a>
<a href="javascript:;" id='yodao_txt' onclick="submit_query('yodao_txt')">有道</a>
<a href="javascript:;" id='yodao_blog' onclick="submit_query('yodao_blog')">博客</a>
<a href="javascript:;" id='google_code' onclick="submit_query('google_code')">代码</a>
<a href="javascript:;" id='google_scholar' onclick="submit_query('google_scholar')">论文</a>
<a href="javascript:;" id='baidu_img' onclick="submit_query('baidu_img')">百图</a>
<a href="javascript:;" id='yodao_img' onclick="submit_query('yodao_img')">有图</a>
<a href="javascript:;" id='yodao_dict' onclick="submit_query('yodao_dict')">词典</a>
<a href="javascript:;" id='iask_ditu' onclick="submit_query('iask_ditu')">地图</a>
<a href="javascript:;" id='verycd' onclick="submit_query('verycd')">CD</a>
<a href="javascript:;" id='yahoo_txt' onclick="submit_query('yahoo_txt')">Yahoo</a>
<a href="javascript:;" id='trans_en' onclick="submit_query('trans_en')">翻译</a>
</td></tr>
</table>

<!--Google站内搜索开始-->
<form method=get action="http://www.google.com/search">
<input type=text name=q>
<input type=submit name=btnG value="Google 搜索">
<input type=hidden name=ie value=GB2312>
<input type=hidden name=oe value=GB2312>
<input type=hidden name=hl value=zh-CN>
<input type=hidden name=domains value="www.pk17s.cn">
<input type=hidden name=sitesearch value="www.pk17s.cn">
</form>
<!--Google站内搜索结束-->

<!--Baidu站内搜索开始-->
<form action="http://www.baidu.com/baidu">
<input type=text name=word>
<input type="submit" value="Baidu 搜索">
<input name=tn type=hidden value="bds">
<input name=cl type=hidden value="3">
<input name=ct type=hidden value="2097152">
<input name=si type=hidden value="www.pk17s.cn">
</form>
<!--Baidu站内搜索结束-->

<!--Yahoo站内搜索开始-->
<form action="http://www.yahoo.com.cn/search">
<input type=text name="p">
<input type="submit" value="Yahoo 搜索">
<input type=hidden name=vs value="www.pk17s.cn">
</form>
<!--Yahoo站内搜索结束-->

  下面是Google和百度的Javascript版的站内搜索代码:

<!--Google站内搜索开始-->
<script type="text/javascript">
function googlesearch () {
var wq=document.getElementsByName("wq")[0].value;
var link="http://www.google.com/search?domains=www.pk17s.cn&sitesearch=www.pk17s.cn&q="+wq;
window.open(link); }
</script>
<input type="text" name="wq"/><input type="submit" onclick="javascript:googlesearch()" value="Google 搜索" />
<!--Google站内搜索结束-->

<!--Baidu站内搜索开始-->
<script language="javascript">
function baidusearch () {
var wd=document.getElementsByName("wd")[0].value;
var link="http://www.baidu.com/s?si=www.pk17s.cn&cl=3&ct=2097152&tn=baidulocal&word="+wd;
window.open(link); }
</script>
<input type="text" name="wd"/><input type="submit" onclick="javascript:baidusearch()" value="Baidu 搜索" />
<!--Baidu站内搜索结束-->
</body>
</html>

1.2.搜索网络上现有的jquery搜索引擎代码.

目前为止,网络上的jquery搜索插件,基本上是使用自己提供一个ajax server代码,然后供插件实时搜索使用.

1.3 预览效果:

image

这是使用1.1百度站内搜索pk17s.cn的示例截图.

image

这是使用插件live search 2.0的示例截图.

2.目标:

实现一款中间是搜索文本框,右边是搜索按钮,最好还有一个语音麦克风按钮.下面一排是各大搜索引擎的单选框.

2.1下面是正文,贡献出我的鲜血:

<html> 
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>pkrss - search page</title>
<meta http-equiv="Author" content="liandeliang@yahoo.com.cn" />
<meta http-equiv="Copyright" content="pkrss.com" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="all" />
<meta name="Distribution" content="global" />
<meta name="keywords" content="pkrss,search page" />
<meta name="description" content="pkrss search page is aggregation many search engine.">
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<meta name="application-name" content="pkrss" />
<meta name="msapplication-tooltip" content="pkrss" />
<meta name="msapplication-starturl" content="./" />
<link type="image/x-icon" href="http://www.pk17s.cn/favicon.ico" rel="SHORTCUT ICON" />
<meta name="msapplication-navbutton-color" content="#219bc0" />
<meta name="msapplication-window" content="width=device-width;height=device-height" />
<meta name="msapplication-task" content="name=pkrss-search;action-uri=http://www.pk17s.cn/p/;icon-uri=http://www.pk17s.cn/favicon.ico" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<style type="text/css">
.normal {font-family: "Verdana","Arial";font-size:14px}
.small {font-family: "Verdana","Arial";font-size:12px}
body { font-family: "Verdana","Arial";font-size:14px}
td {font-family: "Verdana","Arial";font-size:14px}
th {font-family: "Verdana","Arial";font-size:15px}
input {font-family: "Verdana","Arial";font-size:14px}
a {text-decoration:underline; color:blue}
a:link { text-decoration:underline; color: blue }
a:visited { text-decoration:underline; color: blue }
a:hover { text-decoration: underline; color: red }
</style>
</head>
<body>
<form action="javascript:searchSubmit();" onsubmit="javascript:;">
<table border="0" width="100%">
<tr>
<td>
Search:
<input type="text" name="keyword" size="20" id="keyword" />
<input type="submit" value="Search" id="search-btn" class="" />
</td>
</tr>
<tr>
<td id="search_container">
</td>
</tr>
</table>
</form>

<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.1.min.js"></script>
<script type="text/javascript">
var site = "pk17s.cn";
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
var searchs = [
{'name':'google','showtext':'google','src':_bdhmProtocol+'www.google.com/search?domains='+site+'&sitesearch='+site+'&q='},
{'name':'baidu','showtext':'baidu','src':_bdhmProtocol+'www.baidu.com/s?si='+site+'&cl=3&ct=2097152&tn=baidulocal&word='},
{'name':'yahoo','showtext':'yahoo','src':_bdhmProtocol+'www.yahoo.com.cn/search?vs='+site+'&p='}
];
$(document).ready(function(){
var searchitem;
var htmlsrc = '';
var defaultsrc=' checked="checked"';
for(var i=0,c=searchs.length;i<c;++i){
searchitem = searchs[i];
htmlsrc += '<input type="radio" name="searchengine" value="'+searchitem.name+'"'+defaultsrc+' id="searchengine_'+searchitem.name+'"/><label for="searchengine_'+searchitem.name+'">'+searchitem.showtext+'</label>';
defaultsrc = '';
}
$("#search_container").html(htmlsrc);
});
function searchSubmit(){
var searchitem,curitem;
var enginename = $("input:radio[name=searchengine]:checked").val();
for(var i=0,c=searchs.length;i<c;++i){
searchitem = searchs[i];
if(searchitem.name!=enginename)
continue;
curitem = searchitem;
}
if(!curitem)
return;

var keyword = $("#keyword").val();
if(!keyword || (keyword==''))
keyword = site;
var link=curitem.src+keyword;
document.location.href=(link);
}
</script>
</body>
</html>



 





以上鲜血,谢绝任何形式的转载!~~

jquery源码-集成多款播放器的网页

现在网页播放器越来越多了.现在我们为大家提供一款基于多种网页播放器的jquery源码.请看这里,在线示例在这里:

music.htm的源码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--[if lt IE 7 ]> <html class="no-js ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]> <html class="no-js ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]> <html class="no-js ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<title>语音新闻王音乐电台集锦</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link rel='stylesheet' href='css/style.css'>

<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

<script src='js/jquery.min.js'></script>
<script src='js/jquery.color-RGBa-patch.js'></script>
<script src='js/music.js'></script>
</head>
<body>
<header>
<h1> pk17s 音 乐 电 台</h1>
</header>

<div id="music_list" class="nav-wrap">
<ul class="group" id="navmenu"></ul>
</div>

<div class="clearfix" id="div_tab"></div>

<div id="div_pannel" style="height:100%"></div>
</body>
</html>




music.js的源码:


function CreateDiv(tabid, url, name)
{
///如果当前tabid存在直接显示已经打开的tab
if (document.getElementById("div_" + tabid) == null)
{
$('.crent').removeClass('crent');
$('#div_pannel').children().hide();

//创建iframe
var box = document.createElement("iframe");
box.id = "div_" + tabid;
box.src = url;
box.height = "100%";
box.frameBorder = 0;
box.width = "100%";
box.onload=iframeLoadReady;
document.getElementById("div_pannel").appendChild(box);


//创建li菜单
var tab = document.createElement("li");
tab.className = "crent";
tab.id = tabid;
var litxt = "<span><a href=\"javascript:;\" onclick=\"javascript:CreateDiv('" + tabid + "','" + url + "','" + name + "')\" title=" + name + " class=\"menua\">" + name + "</a><a onclick=\"RemoveDiv('" + tabid + "')\" class=\"win_close\" title=\"关闭当前窗口\"><a></span>";
tab.innerHTML = litxt;
document.getElementById("div_tab").appendChild(tab);
}
else
{
var tablist = document.getElementById("div_tab").getElementsByTagName('li');
var pannellist = document.getElementById("div_pannel").getElementsByTagName('iframe');
//alert(tablist.length);
for (i = 0; i < tablist.length; i++)
{
tablist[i].className = "";
pannellist[i].style.display = "none"
}
document.getElementById(tabid).className = 'crent';
document.getElementById("div_" + tabid).style.display = 'block';
}
}
function RemoveDiv(obj)
{
var ob = document.getElementById(obj);
ob.parentNode.removeChild(ob);
var obdiv = document.getElementById("div_" + obj);
obdiv.parentNode.removeChild(obdiv);
var tablist = document.getElementById("div_tab").getElementsByTagName('li');
var pannellist = document.getElementById("div_pannel").getElementsByTagName('iframe');
if (tablist.length > 0)
{
tablist[tablist.length - 1].className = 'crent';
pannellist[tablist.length - 1].style.display = 'block';
}
}
function flashChecker()
{
var hasFlash=0;
var flashVersion=0;
var isIE=/*@cc_on!@*/0;

if(isIE)
{
var swf = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
if(swf) {
hasFlash=1;
VSwf=swf.GetVariable("$version");
flashVersion=parseInt(VSwf.split(" ")[1].split(",")[0]);
}
}else{
if (navigator.plugins && navigator.plugins.length > 0)
{
var swf=navigator.plugins["Shockwave Flash"];
if (swf)
{
hasFlash=1;
var words = swf.description.split(" ");
for (var i = 0; i < words.length; ++i)
{
if (isNaN(parseInt(words[i]))) continue;
flashVersion = parseInt(words[i]);
}
}
}
}
return {f:hasFlash,v:flashVersion};
}

function iframeLoadReady() {
var demoIframe = this;

if(demoIframe.contentWindow==window)
{
var h1=0, h2=0, d=document, dd=d.documentElement;
demoIframe.parentNode.style.height = demoIframe.offsetHeight +"px";
demoIframe.style.height = "10px";

if(dd && dd.scrollHeight) h1=dd.scrollHeight;
if(d.body) h2=d.body.scrollHeight;
var h=Math.max(h1, h2);

if(document.all) {h += 4;}
if(window.opera) {h += 1;}

if(h<400)
h = 400;

demoIframe.style.height = demoIframe.parentNode.style.height = h +"px";
}
}

function createMusicList(){
var list = [
{'name':'grooveshark',url:'http://html5.grooveshark.com/#!/popular',text:'grooveshark','player':'html5'},
{'name':'pk17s',url:'simplemodal_tab_music_pk.htm',text:'pkmusic','player':'html5'},
{'name':'pkradio',url:'simplemodal_tab_rssradio.htm',text:'pkradio','player':'html5'},
{'baidu':'baidu',url:'http://fm.baidu.com/',text:'百度','player':'pc'},
{'kugou':'kugou',url:'http://m.kugou.com/',text:'酷狗','player':'pc'},
{'name':'douban',url:'http://douban.fm/partner/baidu/doubanradio',text:'豆瓣','player':'pc'},
{'name':'kuwo',url:'http://player.kuwo.cn/webmusic/webdiantai/kuwoBaiduPlay.jsp',text:'酷我','player':'pc'},
{'name':'fmqq',url:'http://fm.qq.com',text:'QQ音乐电台','player':'pc'},
{'name':'yqq',url:'http://music.qq.com',text:'QQ网页音乐','player':'pc'}
];
var defaultitem = null;
var setupedflash = flashChecker().f;
var s = '';
var isMobile = navigator.userAgent.match(/mobile/i);
for(var i in list){
var item = list[i];
if(item.player=='pc')
{
if(isMobile)
continue;
}
else if(item.player=='flash')
{
if(!setupedflash){
continue;
}
}
if(!defaultitem)
defaultitem = item;
s += '<li id="nav_li_' + item.name + '"><a href="javascript:onLiItemClick(\''+item.name+'\',\''+item.url+'\',\''+item.text+'\');">'+item.text+'</a></li>';
}
if(!defaultitem)
return;
document.getElementById("navmenu").innerHTML = s;
onLiItemClick(defaultitem.name,defaultitem.url,defaultitem.text);
/* Kick IE into gear */
$(".current_page_item a").mouseenter();
}

function onLiItemClick(tabid, url, name){

$("#navmenu li.current_page_item").removeClass("current_page_item");

CreateDiv(tabid,url,name);

$('#nav_li_'+tabid).addClass("current_page_item");
}

// DOM Ready
$(function() {
createMusicList();

var $el, leftPos, newWidth;
$mainNav2 = $("#navmenu");
$mainNav2.append("<li id='magic-line-two'></li>");

var $magicLineTwo = $("#magic-line-two");
var ol = $(".current_page_item a");
ol = ol.position();
ol = ol.left;
$magicLineTwo
.width($(".current_page_item").width())
.height($mainNav2.height())
.css("left", ol)
.data("origLeft", ol)
.data("origWidth", $magicLineTwo.width())
.data("origColor", "#8DC91E");

$("#navmenu a").hover(function() {
$el = $(this);
leftPos = $el.position().left;
newWidth = $el.parent().width();
$magicLineTwo.stop().animate({
left: leftPos,
width: newWidth,
backgroundColor: "#8DC91E"
})
}, function() {
$magicLineTwo.stop().animate({
left: $magicLineTwo.data("origLeft"),
width: $magicLineTwo.data("origWidth"),
backgroundColor: $magicLineTwo.data("origColor")
});
});
});




其它请见在线示例的文件.

Monday, October 29, 2012

pkrss update-1.1.69

2012-10-29 23:13 by  admin@pk17s.cn

1.fix one pkrsslib.js about catalog bug.

2.change sns share js.

3.reset manifet from cdn.pk17s.cn –> current domain.

4.add donate in default plugin container.

error C2259: “CException”: 不能实例化抽象类

因为VS6后的CException改得太多了,我们只能配合形势.将看Exception的源码:

 

class AFX_NOVTABLE CException : public CObject
{
// abstract class for dynamic type checking
DECLARE_DYNAMIC(CException)

public:
// Constructors
CException(); // sets m_bAutoDelete = TRUE
explicit CException(BOOL bAutoDelete); // sets m_bAutoDelete = bAutoDelete

// Operations
void Delete(); // use to delete exception in 'catch' block

virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
_Out_opt_ PUINT pnHelpContext = NULL) const ;
virtual BOOL GetErrorMessage(_Out_z_cap_(nMaxError) LPTSTR lpszError, _In_ UINT nMaxError,
_Out_opt_ PUINT pnHelpContext = NULL);
virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);

// Implementation (setting m_bAutoDelete to FALSE is advanced)
public:
virtual ~CException() = 0;
BOOL m_bAutoDelete;
#ifdef _DEBUG
void PASCAL operator delete(void* pbData);
void PASCAL operator delete(void* pbData, LPCSTR lpszFileName, int nLine);
protected:
BOOL m_bReadyForDelete;
#endif
};




改成下表给出了MFC 提供的预定义异常:


CMemoryException:内存不足


CFileException:文件异常


CArchiveException:存档/序列化异常


CNotSupportedException:响应对不支持服务的请求


CResourceException:Windows 资源分配异常


CDaoException:数据库异常(DAO 类)


CDBException:数据库异常(ODBC 类)


COleException:OLE 异常


COleDispatchException:调度(自动化)异常


CUserException:用消息框警告用户然后引发


问题2:以一种访问权限不允许的方式做了一个访问套接字的尝试


解决:关闭WINDOWS7的账户控制. 比如:在开始菜单下输入UAC,弹出用户权限控制. 把它拖到最底的选项.

cpp net穿透源码-1.UDP穿透

大家好:

       今天我们的源码示例为"cpp net穿透源码-1.UDP穿透".目标是完成两个内网的用户进行网络穿透的P2P.其中A,B为不同内网的主机,C为一可以公共访问的外网主机.

以下是客户端Client的源码,P2PClient.cpp的Source:


#pragma comment(lib,"ws2_32.lib")

#include "windows.h"
#include "..\proto.h"
#include "..\Exception.h"
#include <iostream>
using namespace std;

UserList ClientList;



#define COMMANDMAXC 256
#define MAXRETRY 5

SOCKET PrimaryUDP;
sockaddr_in PrimaryUDP_sin;
SOCKET PrimaryTCP = 0;

char UserName[10];
char ServerIP[20] = "50.18.251.0";

bool RecvedACK;

void InitWinSock()
{
WSADATA wsaData;

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Windows sockets 2.2 startup");
throw Exception("");
}
else{
printf("Using %s (Status: %s)\n",
wsaData.szDescription, wsaData.szSystemStatus);
printf("with API versions %d.%d to %d.%d\n\n",
LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
}
}

SOCKET mksock(int type)
{
SOCKET sock = socket(AF_INET, type, 0);
if (sock < 0)
{
printf("create socket error");
throw Exception("");
}
return sock;
}

stUserListNode GetUser(char *username)
{
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), username) == 0 )
return *(*UserIterator);
}
throw Exception("not find this user");
}

void BindSock()
{
PrimaryUDP_sin.sin_addr.S_un.S_addr = INADDR_ANY;
PrimaryUDP_sin.sin_family = AF_INET;
PrimaryUDP_sin.sin_port = 0;

int flag=1,flaglen=sizeof(int);

// 重复利用套接字
flag = setsockopt(PrimaryUDP, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, flaglen);

if (bind(PrimaryUDP, (struct sockaddr*)&PrimaryUDP_sin, sizeof(PrimaryUDP_sin)) < 0)
throw Exception("bind error");

int addr_len = sizeof(PrimaryUDP_sin);
if (0 != getsockname(PrimaryUDP, (struct sockaddr*)&PrimaryUDP_sin, &addr_len))
{
throw Exception("bind getsockname error");
}
}

// 接受消息线程
DWORD WINAPI AcceptThreadProc(LPVOID lpParameter)
{
SOCKET connfd;
sockaddr_in sin;
int addr_len = sizeof(sin);

for(;;)
{
if( (connfd =accept(PrimaryTCP,(struct sockaddr*)NULL,NULL)) == -1)
{
cout<<"accept error" << endl;
continue;
}

if (0 != getpeername(connfd, (struct sockaddr*)&sin, &addr_len))
{
cout<<"getpeername accept client error" << endl;
}else{
cout<<"new client connected ok:" << inet_ntoa(sin.sin_addr) << ":" << htons(sin.sin_port) << endl;
}

closesocket(connfd);
}
}

// 绑定本地的UDP端口来监听TCP连接
void ListenTcpSocket()
{
if(PrimaryTCP!=0)
return;

PrimaryTCP = mksock(SOCK_STREAM);

int flag=1,flaglen=sizeof(int);
flag = setsockopt(PrimaryTCP, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, flaglen);

if (bind(PrimaryTCP, (struct sockaddr*)&PrimaryUDP_sin, sizeof(PrimaryUDP_sin)) < 0)
throw Exception("bind tcp socket error");

if( listen(PrimaryTCP,0) == -1) {
throw Exception("listen tcp socket error");
}

cout << "listen tcp socket ok:" << ntohs(PrimaryUDP_sin.sin_port) << endl;

HANDLE threadhandle = CreateThread(NULL, 0, AcceptThreadProc, NULL, NULL, NULL);
CloseHandle(threadhandle);
}

DWORD WINAPI ConnectThreadProc(LPVOID lpParameter)
{
sockaddr_in* remote = (sockaddr_in*)lpParameter;
int remotelen = sizeof(sockaddr_in);
SOCKET tcp = mksock(SOCK_STREAM);

int flag=1,flaglen=sizeof(int);
flag = setsockopt(tcp, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, flaglen);

if (bind(tcp, (struct sockaddr*)&PrimaryUDP_sin, sizeof(PrimaryUDP_sin)) < 0){
remotelen = GetLastError();
throw Exception("bind tcp socket error");
}

unsigned long uio = 1;
ioctlsocket(tcp,FIOASYNC,&uio);

if(0==connect(tcp,(sockaddr*)remote,remotelen)){
cout << "tcp connect ok to:" << inet_ntoa(remote->sin_addr) << ":" << htons(remote->sin_port) << endl;
}else{
cout << "tcp connect error to:" << inet_ntoa(remote->sin_addr) << ":" << htons(remote->sin_port) << endl;
}
closesocket(tcp);
}

// 绑定本地的UDP端口来连接远程TCP连接
void ConnectTcpSocket(sockaddr_in* remote, int remotelen)
{
HANDLE threadhandle = CreateThread(NULL, 0, ConnectThreadProc, remote, NULL, NULL);
CloseHandle(threadhandle);
}

void ConnectToServer(SOCKET sock,char *username, char *serverip)
{
sockaddr_in remote;
remote.sin_addr.S_un.S_addr = inet_addr(serverip);
remote.sin_family = AF_INET;
remote.sin_port = htons(SERVER_PORT);

stMessage sendbuf;
sendbuf.iMessageType = LOGIN;
strncpy(sendbuf.message.loginmember.userName, username, 10);

sendto(sock, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote,sizeof(remote));

int usercount;
int fromlen = sizeof(remote);
int iread = recvfrom(sock, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
if(iread<=0)
{
throw Exception("Login error\n");
}

// 登录到服务端后,接收服务端发来的已经登录的用户的信息
cout<<"Have "<<usercount<<" users logined server:"<<endl;
for(int i = 0;i<usercount;i++)
{
stUserListNode *node = new stUserListNode;
recvfrom(sock, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
ClientList.push_back(node);
cout<<"Username:"<<node->userName<<endl;
in_addr tmp;
tmp.S_un.S_addr = htonl(node->ip);
cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
cout<<"UserPort:"<<node->port<<endl;
cout<<""<<endl;
}
}

void OutputUsage()
{
cout<<"You can input you command:\n"
<<"Command Type:\"send\",\"exit\",\"getu\"\n"
<<"Example : send Username Message\n"
<<" exit\n"
<<" getu\n"
<<endl;
}

/* 这是主要的函数:发送一个消息给某个用户(C)
*流程:直接向某个用户的外网IP发送消息,如果此前没有联系过
* 那么此消息将无法发送,发送端等待超时。
* 超时后,发送端将发送一个请求信息到服务端,
* 要求服务端发送给客户C一个请求,请求C给本机发送打洞消息
* 以上流程将重复MAXRETRY次
*/
bool SendMessageTo(char *UserName, char *Message)
{
char realmessage[256];
unsigned int UserIP;
unsigned short UserPort;
bool FindUser = false;
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), UserName) == 0 )
{
UserIP = (*UserIterator)->ip;
UserPort = (*UserIterator)->port;
FindUser = true;
}
}

if(!FindUser)
return false;

strcpy(realmessage, Message);
for(int i=0;i<MAXRETRY;i++)
{
RecvedACK = false;

sockaddr_in remote;
remote.sin_addr.S_un.S_addr = htonl(UserIP);
remote.sin_family = AF_INET;
remote.sin_port = htons(UserPort);
stP2PMessage MessageHead;
MessageHead.iMessageType = P2PMESSAGE;
MessageHead.iStringLen = (int)strlen(realmessage)+1;
int isend = sendto(PrimaryUDP, (const char *)&MessageHead, sizeof(MessageHead), 0, (const sockaddr*)&remote, sizeof(remote));
isend = sendto(PrimaryUDP, (const char *)&realmessage, MessageHead.iStringLen, 0, (const sockaddr*)&remote, sizeof(remote));

// 等待接收线程将此标记修改
for(int j=0;j<10;j++)
{
if(RecvedACK)
return true;
else
Sleep(300);
}

// 没有接收到目标主机的回应,认为目标主机的端口映射没有
// 打开,那么发送请求信息给服务器,要服务器告诉目标主机
// 打开映射端口(UDP打洞)
sockaddr_in server;
server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);

stMessage transMessage;
transMessage.iMessageType = P2PTRANS;
strcpy(transMessage.message.translatemessage.userName, UserName);

sendto(PrimaryUDP, (const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr*)&server, sizeof(server));
Sleep(100);// 等待对方先发送信息。
}
return false;
}

// 解析命令,暂时只有exit和send命令
// 新增getu命令,获取当前服务器的所有用户
void ParseCommand(char * CommandLine)
{
if(strlen(CommandLine)<4)
return;
char Command[10];
strncpy(Command, CommandLine, 4);
Command[4]='\0';

if(strcmp(Command,"exit")==0)
{
stMessage sendbuf;
sendbuf.iMessageType = LOGOUT;
strncpy(sendbuf.message.logoutmember.userName, UserName, 10);
sockaddr_in server;
server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);

sendto(PrimaryUDP,(const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr *)&server, sizeof(server));
shutdown(PrimaryUDP, 2);
closesocket(PrimaryUDP);
exit(0);
}
else if(strcmp(Command,"send")==0)
{
char sendname[20];
char message[COMMANDMAXC];
int i;
for(i=5;;i++)
{
if(CommandLine[i]!=' ')
sendname[i-5]=CommandLine[i];
else
{
sendname[i-5]='\0';
break;
}
}
strcpy(message, &(CommandLine[i+1]));

if(SendMessageTo(sendname, message))
printf("Send OK!\n");
else
printf("Send Failure!\n");
}
else if(strcmp(Command,"getu")==0)
{
int command = GETALLUSER;
sockaddr_in server;
server.sin_addr.S_un.S_addr = inet_addr(ServerIP);
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);

sendto(PrimaryUDP,(const char*)&command, sizeof(command), 0, (const sockaddr *)&server, sizeof(server));
}
}

// 接受消息线程
DWORD WINAPI RecvThreadProc(LPVOID lpParameter)
{
sockaddr_in remote;
int sinlen = sizeof(remote);
stP2PMessage recvbuf;

for(;;)
{
int iread = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(recvbuf), 0, (sockaddr *)&remote, &sinlen);
if(iread<=0)
{
printf("recv error\n");
continue;
}
switch(recvbuf.iMessageType)
{
case P2PMESSAGE:
{
// 接收到P2P的消息
char *comemessage= new char[recvbuf.iStringLen];
int iread1 = recvfrom(PrimaryUDP, comemessage, 256, 0, (sockaddr *)&remote, &sinlen);
comemessage[iread1-1] = '\0';
if(iread1<=0)
throw Exception("Recv Message Error\n");
else
{
printf("Recv a Message:%s\n",comemessage);

stP2PMessage sendbuf;
sendbuf.iMessageType = P2PMESSAGEACK;
sendto(PrimaryUDP, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote, sizeof(remote));
}

delete []comemessage;
break;

}
case P2PSOMEONEWANTTOCALLYOU:
{
// 接收到打洞命令,向指定的IP地址打洞
printf("Recv p2someonewanttocallyou data\n");

ListenTcpSocket();

sockaddr_in remote;
ZeroMemory(&remote,sizeof(remote));
remote.sin_addr.S_un.S_addr = htonl(recvbuf.iStringLen);
remote.sin_family = AF_INET;
remote.sin_port = htons(recvbuf.Port);

ConnectTcpSocket(&remote,sizeof(remote));

// UDP hole punching
stP2PMessage message;
message.iMessageType = P2PTRASH;
sendto(PrimaryUDP, (const char *)&message, sizeof(message), 0, (const sockaddr*)&remote, sizeof(remote));

break;
}
case P2PMESSAGEACK:
{
// 发送消息的应答
RecvedACK = true;

printf("Recv P2PMESSAGEACK\n");
break;
}
case P2PTRASH:
{
// 对方发送的打洞消息,忽略掉。
//do nothing ...
ListenTcpSocket();

printf("Recv p2ptrash data prepare tcp connect\n");

ConnectTcpSocket(&remote,sinlen);
break;
}
case GETALLUSER:
{
int usercount;
int fromlen = sizeof(remote);
int iread = recvfrom(PrimaryUDP, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
if(iread<=0)
{
throw Exception("Login error\n");
}

ClientList.clear();

cout<<"Have "<<usercount<<" users logined server:"<<endl;
for(int i = 0;i<usercount;i++)
{
stUserListNode *node = new stUserListNode;
recvfrom(PrimaryUDP, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote, &fromlen);
ClientList.push_back(node);
cout<<"Username:"<<node->userName<<endl;
in_addr tmp;
tmp.S_un.S_addr = htonl(node->ip);
cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
cout<<"UserPort:"<<node->port<<endl;
cout<<""<<endl;
}
break;
}
}
}
}


int main(int argc, char* argv[])
{
try
{
InitWinSock();

PrimaryUDP = mksock(SOCK_DGRAM);
BindSock();

if(!ServerIP[0]){
cout<<"Please input server ip:";
cin>>ServerIP;
}

cout<<"Please input your name:";
cin>>UserName;

ConnectToServer(PrimaryUDP, UserName, ServerIP);

HANDLE threadhandle = CreateThread(NULL, 0, RecvThreadProc, NULL, NULL, NULL);
CloseHandle(threadhandle);
OutputUsage();

for(;;)
{
char Command[COMMANDMAXC];
gets(Command);
ParseCommand(Command);
}
}
catch(Exception &e)
{
printf(e.GetMessage());
return 1;
}
return 0;
}





以下是客户端Server的源码,P2PServer.cpp的Source:



#pragma comment(lib, "ws2_32.lib")

#include "windows.h"
#include "..\proto.h"
#include "..\Exception.h"

UserList ClientList;

void InitWinSock()
{
WSADATA wsaData;

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Windows sockets 2.2 startup");
throw Exception("");
}
else{
printf("Using %s (Status: %s)\n",
wsaData.szDescription, wsaData.szSystemStatus);
printf("with API versions %d.%d to %d.%d\n\n",
LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));

}
}

SOCKET mksock(int type)
{
SOCKET sock = socket(AF_INET, type, 0);
if (sock < 0)
{
printf("create socket error");
throw Exception("");
}
return sock;
}

stUserListNode GetUser(char *username)
{
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), username) == 0 )
return *(*UserIterator);
}
throw Exception("not find this user");
}

int main(int argc, char* argv[])
{
try{
InitWinSock();

SOCKET PrimaryUDP;
PrimaryUDP = mksock(SOCK_DGRAM);

sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port= htons(SERVER_PORT);
local.sin_addr.s_addr = htonl(INADDR_ANY);
int nResult=bind(PrimaryUDP,(sockaddr*)&local,sizeof(sockaddr));
if(nResult==SOCKET_ERROR)
throw Exception("bind error");

sockaddr_in sender;
stMessage recvbuf;
memset(&recvbuf,0,sizeof(stMessage));

// 开始主循环.
// 主循环负责下面几件事情:
// 一:读取客户端登陆和登出消息,记录客户列表
// 二:转发客户p2p请求
for(;;)
{
int dwSender = sizeof(sender);
int ret = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender);
if(ret <= 0)
{
printf("recv error");
continue;
}
else
{
int messageType = recvbuf.iMessageType;
switch(messageType){
case LOGIN:
{
// 将这个用户的信息记录到用户列表中
printf("has a user login : %s\n", recvbuf.message.loginmember.userName);
stUserListNode *currentuser = new stUserListNode();
strcpy(currentuser->userName, recvbuf.message.loginmember.userName);
currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr);
currentuser->port = ntohs(sender.sin_port);

ClientList.push_back(currentuser);

// 发送已经登陆的客户信息
int nodecount = (int)ClientList.size();
sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender));
}

break;
}
case LOGOUT:
{
// 将此客户信息删除
printf("has a user logout : %s\n", recvbuf.message.logoutmember.userName);
UserList::iterator removeiterator = ClientList.end();
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 )
{
removeiterator = UserIterator;
break;
}
}
if(removeiterator != ClientList.end())
ClientList.remove(*removeiterator);
break;
}
case P2PTRANS:
{
// 某个客户希望服务端向另外一个客户发送一个打洞消息
printf("%s wants to p2p %s\n",inet_ntoa(sender.sin_addr),recvbuf.message.translatemessage.userName);
stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);
sockaddr_in remote;
remote.sin_family=AF_INET;
remote.sin_port= htons(node.port);
remote.sin_addr.s_addr = htonl(node.ip);

in_addr tmp;
tmp.S_un.S_addr = htonl(node.ip);
printf("the address is %s,and port is %d\n",inet_ntoa(tmp), node.port);

stP2PMessage transMessage;
transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU;
transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr);
transMessage.Port = ntohs(sender.sin_port);

sendto(PrimaryUDP,(const char*)&transMessage, sizeof(transMessage), 0, (const sockaddr *)&remote, sizeof(remote));

break;
}

case GETALLUSER:
{
int command = GETALLUSER;
sendto(PrimaryUDP, (const char*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));

int nodecount = (int)ClientList.size();
sendto(PrimaryUDP, (const char*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));

for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
sendto(PrimaryUDP, (const char*)(*UserIterator), sizeof(stUserListNode), 0, (const sockaddr*)&sender, sizeof(sender));
}
break;
}
}
}
}

}
catch(Exception &e)
{
printf(e.GetMessage());
return 1;
}

return 0;
}


以下是公用文件proto.h的source:

   1:   
   2:  #pragma once
   3:  #include <list>
   4:   
   5:  // 定义iMessageType的值
   6:  #define LOGIN 1
   7:  #define LOGOUT 2
   8:  #define P2PTRANS 3
   9:  #define GETALLUSER  4
  10:   
  11:  // 服务器端口
  12:  #define SERVER_PORT 2280
  13:   
  14:  // Client登录时向服务器发送的消息
  15:  struct stLoginMessage
  16:  {
  17:      char userName[10];
  18:      char password[10];
  19:  };
  20:   
  21:  // Client注销时发送的消息
  22:  struct stLogoutMessage
  23:  {
  24:      char userName[10];
  25:  };
  26:   
  27:  // Client向服务器请求另外一个Client(userName)向自己方向发送UDP打洞消息
  28:  struct stP2PTranslate
  29:  {
  30:      char userName[10];
  31:  };
  32:   
  33:  // Client向服务器发送的消息格式
  34:  struct stMessage
  35:  {
  36:      int iMessageType;
  37:      union _message
  38:      {
  39:          stLoginMessage loginmember;
  40:          stLogoutMessage logoutmember;
  41:          stP2PTranslate translatemessage;
  42:      }message;
  43:  };
  44:   
  45:  // 客户节点信息
  46:  struct stUserListNode
  47:  {
  48:      char userName[10];
  49:      unsigned int ip;
  50:      unsigned short port;
  51:  };
  52:   
  53:  // Server向Client发送的消息
  54:  struct stServerToClient
  55:  {
  56:      int iMessageType;
  57:      union _message
  58:      {
  59:          stUserListNode user;
  60:      }message;
  61:   
  62:  };
  63:   
  64:  //======================================
  65:  // 下面的协议用于客户端之间的通信
  66:  //======================================
  67:  #define P2PMESSAGE 100               // 发送消息
  68:  #define P2PMESSAGEACK 101            // 收到消息的应答
  69:  #define P2PSOMEONEWANTTOCALLYOU 102  // 服务器向客户端发送的消息
  70:                                       // 希望此客户端发送一个UDP打洞包
  71:  #define P2PTRASH        103          // 客户端发送的打洞包,接收端应该忽略此消息
  72:   
  73:  // 客户端之间发送消息格式
  74:  struct stP2PMessage
  75:  {
  76:      int iMessageType;
  77:      int iStringLen;         // or IP address
  78:      unsigned short Port; 
  79:  };
  80:   
  81:  using namespace std;
  82:  typedef list<stUserListNode *> UserList;
  83:   



 


以下是公共文件Exception.h的源码:

   1:   
   2:  #ifndef __HZH_Exception__
   3:  #define __HZH_Exception__
   4:   
   5:  #define EXCEPTION_MESSAGE_MAXLEN 256
   6:  #include "string.h"
   7:   
   8:  class Exception
   9:  {
  10:  private:
  11:      char m_ExceptionMessage[EXCEPTION_MESSAGE_MAXLEN];
  12:  public:
  13:      Exception(char *msg)
  14:      {
  15:          strncpy(m_ExceptionMessage, msg, EXCEPTION_MESSAGE_MAXLEN);
  16:      }
  17:   
  18:      char *GetMessage()
  19:      {
  20:          return m_ExceptionMessage;
  21:      }
  22:  };
  23:   
  24:   
  25:   
  26:  #endif




经过测试,以上示例A向S请求向A发消息后,B够接收S转发的A的消息.但是A收不到B的直接消息.且TCP连接不能成功.请看后面的继续穿透示例.