关于dht办事器的代码实现的信息
admin 发布:2022-12-19 03:19 123
今天给各位分享dht办事器的代码实现的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、如何用c++写一个dht爬虫
- 2、基于stm32的多功能时钟2——DHT11测量温湿度
- 3、DHT11数字传感器与单片机怎么实现连接。
- 4、dht是什么?
- 5、请问一下,BT下载里面的DHT技术到底是什么意思?
如何用c++写一个dht爬虫
要想爬,先读取HTTP
读取后 进行字符串分割
Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,程序中使用POST方式,
提交数据并从服务器获取返回值。
为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。
程序中,通过一个宏的设置来决定是使用WinHttp还是WinINet。
#define USE_WINHTTP //Comment this line to user wininet.
下面来说说实现Http访问的流程(两套API都一样的流程):
1, 首先我们打开一个Session获得一个HINTERNET session句柄;
2, 然后我们使用这个session句柄与服务器连接得到一个HINTERNET connect句柄;
3, 然后我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;
4, 这时我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;
5, 最后依次关闭request,connect,session句柄。
/***********************定义HTTP发送所用方法***********************************/
HINTERNET OpenSession(LPCWSTR userAgent = 0)
{
#ifdef USE_WINHTTP
return WinHttpOpen(userAgent, NULL, NULL, NULL, NULL);;
#else
return InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
#endif
}
HINTERNET Connect(HINTERNET hSession, LPCWSTR serverAddr, int portNo)
{
#ifdef USE_WINHTTP
return WinHttpConnect(hSession, serverAddr, (INTERNET_PORT) portNo, 0);
#else
return InternetConnect(hSession, serverAddr, portNo, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
#endif
}
HINTERNET OpenRequest(HINTERNET hConnect, LPCWSTR verb, LPCWSTR objectName, int scheme)
{
DWORD flags = 0;
#ifdef USE_WINHTTP
if (scheme == INTERNET_SCHEME_HTTPS) {
flags |= WINHTTP_FLAG_SECURE;
}
return WinHttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags);
#else
if (scheme == INTERNET_SCHEME_HTTPS) {
flags |= INTERNET_FLAG_SECURE;
}
return HttpOpenRequest(hConnect, verb, objectName, NULL, NULL, NULL, flags, 0);
#endif
}
BOOL AddRequestHeaders(HINTERNET hRequest, LPCWSTR header)
{
SIZE_T len = lstrlenW(header);
#ifdef USE_WINHTTP
return WinHttpAddRequestHeaders(hRequest, header, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);
#else
return HttpAddRequestHeaders(hRequest, header, DWORD(len), HTTP_ADDREQ_FLAG_ADD);
#endif
}
BOOL SendRequest(HINTERNET hRequest, const void* body, DWORD size)
{
#ifdef USE_WINHTTP
return WinHttpSendRequest(hRequest, 0, 0, const_castvoid*(body), size, size, 0);
#else
return HttpSendRequest(hRequest, 0, 0, const_castvoid*(body), size);
#endif
}
BOOL EndRequest(HINTERNET hRequest)
{
#ifdef USE_WINHTTP
return WinHttpReceiveResponse(hRequest, 0);
#else
// if you use HttpSendRequestEx to send request then use HttpEndRequest in here!
return TRUE;
#endif
}
BOOL QueryInfo(HINTERNET hRequest, int queryId, char* szBuf, DWORD* pdwSize)
{
#ifdef USE_WINHTTP
return WinHttpQueryHeaders(hRequest, (DWORD) queryId, 0, szBuf, pdwSize, 0);
#else
return HttpQueryInfo(hRequest, queryId, szBuf, pdwSize, 0);
#endif
}
BOOL ReadData(HINTERNET hRequest, void* buffer, DWORD length, DWORD* cbRead)
{
#ifdef USE_WINHTTP
return WinHttpReadData(hRequest, buffer, length, cbRead);
#else
return InternetReadFile(hRequest, buffer, length, cbRead);
#endif
}
void CloseInternetHandle(HINTERNET hInternet)
{
if (hInternet)
{
#ifdef USE_WINHTTP
WinHttpCloseHandle(hInternet);
#else
InternetCloseHandle(hInternet);
#endif
}
}
/**********************************************************/
///通过Http方式发送短信
string SendSMS_HTTP(const long ececcid,const string password ,const string msisdn, const string smsContent)
{
string rtnStr ="-1";
HINTERNET hSession = 0;
HINTERNET hConnect = 0;
HINTERNET hRequest = 0;
wstring strHeader(L"Content-type: application/x-www-form-urlencoded\r\n");
// Test data
CrackedUrl crackedUrl(L"");
string StrPostData = "ececcid=600000password="+password+"msisdn="+msisdn+"smscontent="+smsContent+"msgtype=5longcode=";
StrPostData = string_To_UTF8(StrPostData);
// Open session.
hSession = OpenSession(L"HttpPost by lyz_sea@163.com");
if (hSession == NULL) {
cout"Error:Open session!\n";
return "-1";
}
// Connect.
hConnect = Connect(hSession, crackedUrl.GetHostName(), crackedUrl.GetPort());
if (hConnect == NULL) {
cout"Error:Connect failed!\n";
return "-1";
}
// Open request.
hRequest = OpenRequest(hConnect, L"POST", crackedUrl.GetPath(), crackedUrl.GetScheme());
if (hRequest == NULL) {
cout"Error:OpenRequest failed!\n";
return "-1";
}
// Add request header.
if (!AddRequestHeaders(hRequest, strHeader.c_str())) {
cout"Error:AddRequestHeaders failed!\n";
return "-1";
}
// Send post data.
if (!SendRequest(hRequest, StrPostData.c_str(), StrPostData.length())) {
cout"Error:SendRequest failed!\n";
return "-1";
}
// End request
if (!EndRequest(hRequest)) {
cout"Error:EndRequest failed!\n";
return "-1";
}
char szBuf[BUF_SIZE];
DWORD dwSize = 0;
szBuf[0] = 0;
// Query header info.
#ifdef USE_WINHTTP
int contextLengthId = WINHTTP_QUERY_CONTENT_LENGTH;
int statusCodeId = WINHTTP_QUERY_STATUS_CODE;
int statusTextId = WINHTTP_QUERY_STATUS_TEXT;
#else
int contextLengthId = HTTP_QUERY_CONTENT_LENGTH;
int statusCodeId = HTTP_QUERY_STATUS_CODE;
int statusTextId = HTTP_QUERY_STATUS_TEXT;
#endif
dwSize = BUF_SIZE;
if (QueryInfo(hRequest, contextLengthId, szBuf, dwSize)) {
szBuf[dwSize] = 0;
cout"Content length: "szBufendl;
}
dwSize = BUF_SIZE;
if (QueryInfo(hRequest, statusCodeId, szBuf, dwSize)) {
szBuf[dwSize] = 0;
cout"Status code: " szBufendl;
}
dwSize = BUF_SIZE;
if (QueryInfo(hRequest, statusTextId, szBuf, dwSize)) {
szBuf[dwSize] = 0;
cout"Status text:"szBufendl;
}
// read data.
for (;;) {
dwSize = BUF_SIZE;
if (ReadData(hRequest, szBuf, dwSize, dwSize) == FALSE) {
break;
}
if (dwSize = 0) {
break;
}
szBuf[dwSize] = 0;
rtnStr =::UTF8_To_string(string(szBuf));
coutrtnStrendl;//Output 返回值
}
CloseInternetHandle(hRequest);
CloseInternetHandle(hConnect);
CloseInternetHandle(hSession);
return rtnStr;
}
以上方法中用到的CrackURL方法在以下CrackURL.h文件中:
#pragma once
//#includeiostream
//using namespace std;
#define USE_WINHTTP //Comment this line to user wininet.
#ifdef USE_WINHTTP
#include winhttp.h
#pragma comment(lib, "winhttp.lib")
#else
#include wininet.h
#pragma comment(lib, "wininet.lib")
#endif
// CrackedUrl
class CrackedUrl {
int m_scheme;
wstring m_host;
int m_port;
wstring m_path;
public:
CrackedUrl(LPCWSTR url)
{
URL_COMPONENTS uc = { 0};
uc.dwStructSize = sizeof(uc);
const DWORD BUF_LEN = 256;
WCHAR host[BUF_LEN];
uc.lpszHostName = host;
uc.dwHostNameLength = BUF_LEN;
WCHAR path[BUF_LEN];
uc.lpszUrlPath = path;
uc.dwUrlPathLength = BUF_LEN;
WCHAR extra[BUF_LEN];
uc.lpszExtraInfo = extra;
uc.dwExtraInfoLength = BUF_LEN;
#ifdef USE_WINHTTP
if (!WinHttpCrackUrl(url, 0, ICU_ESCAPE, uc)) {
cout"Error:WinHttpCrackUrl failed!\n";
}
#else
if (!InternetCrackUrl(url, 0, ICU_ESCAPE, uc)) {
printf("Error:InternetCrackUrl failed!\n");
}
#endif
m_scheme = uc.nScheme;
m_host = host;
m_port = uc.nPort;
m_path = path;
}
int GetScheme() const
{
return m_scheme;
}
LPCWSTR GetHostName() const
{
return m_host.c_str();
}
int GetPort() const
{
return m_port;
}
LPCWSTR GetPath() const
{
return m_path.c_str();
}
static string UrlEncode(const char* p)
{
if (p == 0) {
return string();
}
string buf;
for (;;) {
int ch = (BYTE) (*(p++));
if (ch == '\0') {
break;
}
if (isalnum(ch) || ch == '_' || ch == '-' || ch == '.') {
buf += (char)ch;
}
else if (ch == ' ') {
buf += '+';
}
else {
char c[16];
wsprintfA(c, "%%%02X", ch);
buf += c;
}
}
return buf;
}
};
基于stm32的多功能时钟2——DHT11测量温湿度
亲爱的读者们,我又回来了~
上一章中,我带着大家实现了时钟显示和按键调整的功能。在这一章中,我将利用DHT11温湿度传感器,来测量环境温度和湿度。
DHT11温湿度传感器是数字式的,包括1个电阻式感湿元件和1个NTC测温元件,内部自带AD转换功能,采用单总线,具有响应快、抗干扰能力强、性价比高等特点。该模块总共4个引脚,其中两个是电源引脚VCC和GND,一个是数据引脚,还有一个为空引脚。
目前流行的数据传输总线有II2C总线,SPI总线,单总线等,而DHT11则采用单总线传输数据。单总线,顾名思义,就是采用单根信号线,即可传输时钟,又能传输数据,而且数据传输是双向的,从而有主机和从机之别。在这里,stm32作为核心控制器,所以是主机,而DHT11为从机。 采用单总线进行数据传输,我们需要查看数据手册的时序图。
总线空闲状态为高电平,主机把总线拉低等待 DHT11 响应,主机把总线拉低必须大于 18 毫秒,保证 DHT11 能检测到起始信号。DHT11 接收到主机的开始信号后, 等待主机开始信号结束,然后发送 80us 低电平响应信号.主机发送开始信号结束后,延时等待 20-40us 后, 读取 DHT11 的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
根据时序图,单片机需要先将总线拉低至少18ms,然后拉高总线20~40us,此时主机的开始信号结束,检测DHT11的响应信号。如果检测到低电平,则DHT11响应,并且低电平时间维持80us,然后DHT11拉高总线80us。此时DHT11准备传输数据,传输的数据间隙为50us低电平,传输的数据通过高电平的时间长短来区分"0"和"1"。数据传输完毕,DHT11将总线拉低50us,最后主机再拉高总线。
(1)编写延时函数
由于DHT11的时序比较严格,需要毫秒级别和微妙级别的延时。这里我们采用Systick去做延时。在之前按键扫描函数里也用到延时的,在此我叙述一下。
我们需要配置系统时钟,然后把Systick设置成72,这样就能产生1us时间基准,其次编写Systick中断处理函数,让变量自减,从而达到延时的效果,最后编写延时函数,也就是对自减的变量赋初始值。
__IO uint32_t TimingDelay;
/*配置SysTick函数*/
void systick_init(void)
{
/*配置Systick重载值,系统时钟为72MHz*/
/*设置72,中断时间:72*(1/72000000) = 1us*/
if(SysTick_Config(72)==1) //若SysTick_Config函数返回产生中断信号,返回值为0
{
while(1); //SysTick_Config函数返回值为1,则等待
}
}
/*时间变量自减函数*/
void TimingDelay_Decrement(void)
{
if(TimingDelay!=0x00)
{
TimingDelay--;
}
}
/*SysTick中断处理函数*/
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
/*延时函数,时间基准为1ms*/
void delay_ms(__IO uint32_t nTime)
{
TimingDelay = nTime*1000;
while(TimingDelay!=0);
}
/*延时函数,时间基准为1us*/
void delay_us(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay!=0);
}
(2)配置相应的GPIO口作为单总线数据端
/*配置DHT11数据引脚,设置成浮空输入模式*/
void dht11_gpio_portIn(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, GPIO_InitStructure);
}
/*配置DHT11数据引脚,设置成推挽输出模式*/
void dht11_gpio_portOut(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, GPIO_InitStructure);
}
由于DHT11采用单总线通信协议,所以数据传输是双向的,所以分别将数据端口设置成浮空输入模式和推挽输出模式。并且将数据口的输入和输出定义成宏定义的形式。
#define DHT11_OUT_H GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define DHT11_OUT_L GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define DHT11_IN GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)
(3)根据DHT11时序图,编写时序函数
现在,我们开始编写总线的驱动函数,根据时序图,主机发送命令启动转换,接着,等待DHT11转换响应并且输出数据,最后读取数据。
/*启动总线函数*/
void dht11_reset(void)
{
dht11_gpio_portOut(); //设置成输出模式
DHT11_OUT_L; //主机将总线拉低至少18ms
delay_ms(18);
DHT11_OUT_H; //主机拉高保持20~40us
delay_us(30);
dht11_gpio_portIn(); //设置成输入模式,等待DHT11响应
}
/*DHT11响应函数*/
u8 dht11_scan(void)
{
return DHT11_IN; //返回值为DHT11的响应信号
}
实时监控DHT11的数据线,直至其产生出低电平,表示DHT11响应主机请求,开始传输数据。
/*DHT11读取位函数*/
u8 dht11_read_bit(void)
{
while(DHT11_IN==RESET); //传输数据位前存在50us低电平
delay_us(40); //根据高电平的时间长短决定电平是1还是0
if(DHT11_IN==SET) //"0"电平持续时间为26~28us,"1"电平持续时间为70us
{
while(DHT11_IN==SET);
return 1; //若检测到高电平,返回值为1
}
else
{
return 0; //若检测到高电平,返回值为0
}
}
/*DHT11读取字节函数*/
//注:数据最高位先传输
u8 dht11_read_byte(void)
{
u8 i,dat = 0x00;
for(i=0; i8; i++)
{
dat = dat1;
dat = dat|dht11_read_bit();//将串行数据读取出来
}
return dat;
}
当DHT11响应后,就开始通过单总线传输数据,在读取位函数里,通过高电平的时间长短来判断输出的是'1'还是'0',在读取字节函数里,调用读取位函数,将传输的每8位整合出字节,并读取出来。
我们查阅DHT11数据手册,得知数据传输的结构(依次顺序):湿度整数部分(1字节)、湿度小数部分(1字节)、温度整数部分(1字节)、温度小数部分(1字节)、校验和(1字节)。这里,其实就是一个简单的通信协议。校验和就是源数据所有字节之和的低8位,确保传输数据的正确与稳定。
/*DHT11读取数据函数*/
u8 dht11_read_data(void)
{
u8 i;
dht11_reset();
if(dht11_scan()==RESET) //DHT11发出响应信号
{
while(DHT11_IN==RESET); //DHT11拉低总线80us
while(DHT11_IN!=RESET); //DHT11拉高总线80us
for(i=0; i5; i++)
{
buffer[i] = dht11_read_byte();
}
while(DHT11_IN==RESET); //发送完最后1bit数据后,等待50us低电平结束
dht11_gpio_portOut();
DHT11_OUT_H; //主机拉高总线
if(buffer[0]+buffer[1]+buffer[2]+buffer[3]==buffer[4])
{
return 1; //校验成功
}
else
{
return 0; //校验失败
}
}
else
{
return 0; //DHT11未发出响应信号
}
}
在读取字节里,先等待DHT11响应,然后开始接收数据,并且连续读取5次,存放在事先定义好的数组里,主机发出结束信号,最后对读取的数据进行校验。
(4)测量显示温湿度
主函数调用DHT11读数据函数,并调用lcd显示函数,将温度和湿度显示出来即可。
if(dht11_read_data()==1)//读取数据,前提是DHT11响应,并且数据校验成功
{
humidity = buffer[0];//buffer[0]存放的是湿度整数部分
temperature = buffer[2];//buffer[2]存放的是温度整数部分
}
lcd_display_string(2,0,"温度");
lcd_display_num_m(2,32,temperature/10);
lcd_display_num_m(2,40,temperature%10);
lcd_display_string(4,0,“湿度”);
lcd_display_num_m(4,32,humidity/10);
lcd_display_num_m(4,40,humidity%10);
至此,通过本章的讲解,我相信,大家应该对于DHT11模块有了大致的了解,当然,如果你只是看看文章的话,可能效果不怎么理想。这些东西,都需要亲自动手的,正所谓"实践出真知"。所以,你可以在网上买开发板,再买一些模块,不一定要和我的一样。当然,想要挑战自己的话,可以买块最小系统板,这样,外围的硬件电路可以由自己搭建(功能自定义),灵活性强的同时,也锻炼了自己的动手能力。如果你是会设计PCB的大佬,那更好,估计你的水平,就浏览一下我的文章即可。
DHT11数字传感器与单片机怎么实现连接。
四条引角中有两条是电源引脚,有两条是输出数据的引脚,只需要给他供上额定电压,然后再他的输出引脚采集信号就可以了,输出信号如果是模拟量的话,通过A/D芯片,将模拟量转换为数字信号,然后传送给单片机。
DHT11是数字传感器,所以不需要进行模数的转换,具体接口如下
引脚1: VDD 供电3-5.5VDC
引脚2: DATA 串行数据,单总线
引脚3:NC 空脚,请悬空
引脚4:GND 接地,电源负极
注意:引脚2在接单片机时,同时要在数据线接一上拉电阻,接到电源上。
数字传感器是指将传统的模拟式传感器经过加装或改造A/D转换模块,使之输出信号为数字量(或数字编码)的传感器,主要包括:放大器、A/D转换器、微处理器(CPU)、存储器、通讯接口、温度测试电路等。
数字传感器特点:
1、先进的A/D转换技术和智能滤波算法,在满量程的情况下仍可保证输出码的稳定。
2、可行的数据存储技术,保证模块参数不会丢失。
3、良好的电磁兼容性能。
4、传感器的性能采用数字化误差补偿技术和高度集成化电子元件,用软件实现传感器的线性、零点、温漂、蠕变等性能参数的综合补偿,消除了人为因素对补偿的影响,大大提高了传感器综合精度和可靠性。
5、传感器的输出一致性误差可以达到0.02%以内甚至更高,传感器的特性参数可完全相同,因而具有良好的互换性。
6、采用A/D转换电路、数字化信号传输和数字滤波技术,传感器的抗干扰能力增加,信号传输距离远,提高了传感器的稳定性。
7、数字传感器能自动采集数据并可预处理、存储和记忆,具有唯一标记,便于故障诊断。
8、传感器采用标准的数字通讯接口,可直接连入计算机,也可与标准工业控制总线连接,方便灵活。
9, 数字传感器是将AD,EPROM,DIE(传感器芯片),封装在一块用PCB,金属块或陶瓷板上的集成。通过各种温度,压力点的校准,计算出DIE的线性,再利用AD去补偿的方法加工而成的。
dht是什么?
DHT类似Tracker的根据种子特征码返回种子信息的网络。DHT全称叫分布式哈希表(Distributed Hash Table),是一种分布式存储方法。
在不需要服务器的情况下,每个客户端负责一个小范围的路由,并负责存储一小部分数据,从而实现整个DHT网络的寻址和存储。
新版BitComet允许同时连接DHT网络和Tracker,也就是说在完全不连上Tracker服务器的情况下,也可以很好的下载,因为它可以在DHT网络中寻找下载同一文件的其他用户。
相关信息:
一般用户是完全不需要理会这个具体过程的。这里可以简单的介绍一下:连入DHT网络的用户叫做节点(node),节点之间互相有路由记录,因此只要和任何一个已经在DHT网络中的节点连接上,客户端就可以寻找到更多的节点,从而连入网络。
简单地说:DHT技术就是可以使得网络中的任何一个机器都实现服务器的部分功能,使得用户的下载不再依靠于服务器。用户不需要干涉这个功能。对于普通用户来说,不明白也没有关系。
请问一下,BT下载里面的DHT技术到底是什么意思?
DHT网路的介绍
DHT网路的介绍
评论:新版Bitcomet发布,DHT加深反盗难度
本文已发表于《电脑商情报•家用电脑》
2005年6月8日,著名的BT下载软体Bitcomet升级到版本0.59。这次的升级与以往不同,它包含著里程碑式的改变——其开始“支援连入公用DHT网路,实现无Tracker下载”。联想到此前另一著名BT用户端Azureus从2.3.0.0,以及BT官方的BitTorrent从Beta 4.1.0开始使用的"trackerless" torrents,BT下载已经进入崭新的DHT时代。
那麼,DHT究竟为BT带来了什麼?我们采访了Bitcomet的作者灿烂微笑,并将在此文中加以剖析。
一、实战新版Bitcomet
目前国内用户使用最多的BT用户端就是Bitcomet,因此我们在这裏也以它为例讲解DHT网路的使用。
默认情况下,无须做任何设置BitComet即可自动连接并使用DHT网路。启动软体,它会使用和TCP埠号相同的UDP埠进行DHT网路连接。此时,用户可以在Bitcomet的状态条上得到DHT网路连接的状态。
当然,如果要顺利使用DHT功能,除了连接DHT网路之外,还需要档的发布者在制作种子的时候就打开DHT选项。单击功能表“档”-“制作Torrent档”,在弹出的视窗中,就可以调节是否让种子使用DHT网路,共有三种选择。
“使用公用DHT网路(推荐)”表示种子同时使用Tracker伺服器和公用DHT网路来寻找用户,列表框中可以填写传统Tracker伺服器位址或者DHT网路节点位址,也可以只填其中一种,也可以什麼都不填。什麼都不填代表仅仅使用DHT网路,自动连接节点;只填写DHT网路节点代表仅仅使用DHT网路,而且默认连接这几个填写的节点;只填写Tracker代表同时使用Tracker和DHT网路,自动连接Tracker伺服器和节点;同时填写Tracker和DHT网路节点代表同时使用Tracker和DHT网路,而且默认连接这几个Tracker伺服器和节点。总之,此种方式下的BT种子将采取尽可能多的方式进行连接,因此建议种子制作者保持这个默认选项,列表框中像往常一样填写一两个普通的Tracker伺服器地址。
另外两个选择:“不使用公用DHT网路(优先使用Tracker伺服器)”表示在不能链结上Tracker伺服器的情况下使用DHT网路功能,如果能链结上Tracker伺服器,就不使用DHT网路功能;“仅从Tracker伺服器获取用户资讯(禁用DHT及用户来源交换)”则代表禁止使用公用DHT网路以及用户来源交换来寻找用户,完全禁用DHT网路功能,相当於Azureus软体的“安全Torrent”。
如果你不想用Bitcomet的DHT网路功能,则可以在“选项”-“高级设置”中去掉“自动添加DHT网路作为备用Tracker”,并在其下的“网路连接”中去掉“允许加入到公用DHT网路”前面的勾。
在Azureus和BitTorrent Beta中制作支援DHT功能的种子,以及使用DHT网路同样简单,只不过它们的DHT网路功能都没有Bitcomet这麼强大。因此Bitcomet可以同时支援DHT网路和Tracker伺服器,而其他两种软体同时只能支援这两者之一。
有关BT之DHT网路的使用,还请参看我的另外一篇文章--实战BT之DHT网路。
二、DHT技术让反盗版更加困难?
在多数人眼中,任何P2P技术的改进都与版权的博奕脱不了干系,DHT网路能够引起如此注目亦是如此。
确实,BT采用DHT网路后,反盗版将变得更加困难。因为在此之前,用户进行BT下载时,必需首先连接上Tracker伺服器,根据所获得的正在进行下载和上传的用户列表,才能够进行正常的档交换。这样的话,只需封禁掉提供Tracker服务的网站,便可以截断盗版传播的途径。DHT网路则不同,由於此时互联网中任何一个运行BT用户端的用户都可以作为DHT网路中的节点,因此即使封禁掉那些提供Tracker服务的网站,用户还是能够通过全球范围的逻辑DHT网路分享档,反盗版就无从谈起。除非让世界上的人都不上网,或宣布使用BT软体为重罪。
不过,在我们对Bitcomet作者的采访中,他否认了DHT网路是为了更好的传播盗版。他指出,DHT网路的“主要优势是稳定性,本来Tracker伺服器人多了很容易宕机,但是DHT网路没有这个问题,再多的人也没事”。
这一切还是印证著那句话——“技术从来都是一把双刃剑”。在批判BT助长盗版气焰的同时,我们也应该看到,BT也正在日渐成为合法作品传播的途径。由於无法承受大流量的访问,一些免费和共用软体(如Foobar2000等)开始采用BT方式分发,大型的合法软体——Linux系统,更是将BT作为主要的分发管道。这种良性的应用可能会为BitTorrent带来一定的法律保护,使BT下载商业化甚至合法化。
而随著DHT技术的采用,这种应用还将向纵深发展。虽然它加重了反盗版的难度,但也将使合法分发各种文件更加容易。事物就是如此辩证,但笔者相信P2P软体一定能够寻求到一个更加合理的应用。
三、主要优势在於稳定--采访Bitcomet作者“灿烂微笑”
Bitcomet 0.59发布笠日,我们有幸通过MSN Messenger采访了Bitcomet的作者“灿烂微笑”(网名),请他来谈一下使用DHT网路后的BT:
问:BT的各个用户端软体是从什麼时候开始用DHT的?它与eMule中的Kad有何不同?
答:BitTorrent是5月份开始测试DHT的,Azureus比较早,但糟糕的是它们两个不互通。eMule中的Kad也是DHT的一种,不过它的实现协议与BT中的并不相同,所以不能互通。 Bitcomet中的DHT与BitTorrent是相容的。
问:为何会出现不互通的现像呢?
答:开发者不同,而且在这个DHT问题上互相之间没有协调好,所以就成了现在这样。更糟糕的是Azureus的DHT代码很长,我却找不到协议文档。
问:对一个用户来说,它获得一个使用DHT网路的种子后,启动Bitcomet进行下载,这时软体是如何连接的?
答:用户打开软体以后就连入网路了,启动使用DHT网路的种子的任务后,Bitcomet就会在DHT网路中搜索。种子上如果有默认节点,那麼可以帮助没有连入网路的用户通过那些节点连入网路,如果下载者已经联入DHT网路了,种子裏填写的节点就不需要了。Bitcomet内置了2个节点,分别是node://router.bittorrent.com:6881和node://router.bitcomet.net:554。其实任何一个长期线上的用户都可以做个好节点。
问:如果这两个长期线上的内置节点出现问题时,是不是就连接不上DHT网路了?
答:不会,这个只是最初的连接用的,如果它们都失效了,那麼1.曾经连上过DHT的用户保存了其他节点,所以只要不要很长时间不用,应该还可以连上;2.新的用户可以通过打开带有DHT节点的种子连入。
问:那麼,DHT网路相比Tracker伺服器来说,有什麼主要的优势?是不是以前下载时,种子只是同时连接同一台Tracker伺服器的下载者,而现在却可以搜索整个DHT网路中,得到更多的源?
答:主要优势是稳定性,本来Tracker伺服器人多了很容易宕机,但是DHT网路没有这个问题,再多的人也没事。如果是单个档的种子,确实也有你说的好处。
问:刚才你说Emule也用DHT,那麼相比之下,BT协议在技术上的优势是什麼呢?
答:应该说BT的DHT才刚开始,eMule应该测试了有1年左右了,BT的优势可能还是原来的吧,就是对新的东西分享比较快。
问:你是如何看待BT下载和软体版权问题的?
答:这个……有难度啊!BT本来只是一种不错的P2P网路技术,我觉得它的流行也代表了一种市场需要吧,说明通过互联网分发作品的可能的价值。虽然目前BT有些被滥用了,不过我想这种P2P技术应该能够寻求到一个更加合理的应用,就像Skype的创始人原来做的是Kazza一样。
问:再问一个读者关心的问题,你认为BT伤硬碟麼?
答:软体刚出来的时候,没有任何缓冲,完全大范围随机地按16K来读写硬碟,所以确实对硬碟不好(不过要速度快的时候才有影响)。当然后来就在软体裏面做缓存了,这个问题就基本不存在了。
问:最后一个问题,你自己经常使用BT下载吗?
答:我很久没用了(很出乎意料吧),不过感觉DHT很好玩,现在的乐趣更多是在编写软体上了。
DHT网路
DHT的全称是Distributed Hash Table,即分散式哈希表技术,是一种分散式存储方法。这种网路不需要中心节点伺服器,而是每个用户端负责一个小范围的路由,并负责存储一小部分资料,从而实现整个DHT网路的定址和存储。和中心节点伺服器不同,DHT网路中的各节点并不需要维护整个网路的资讯,而是只在节点中存储其临近的后继节点资讯,大幅减少了带宽的占用和资源的消耗。DHT网路还在与关键字最接近的节点上复制备份冗余资讯,避免了单一节点失效问题。
形象地,我们可以把整个DHT网路想像成一个大城市,那麼每个用户端,就好比城市裏各个角落的地图,上面绘制了附近区域的地形情况,把这些地图一汇总,城市的全貌就出来了。
而DHT所采用的演算法中最出名的是Kademlia,eMule早在一年多前就开始采用,Bitcomet、Azureus和BitTorrent只是步其后尘,同样使用Kademlia演算法的DHT。不过它们各自的实现协议不尽相同,因此不能相互相容(BitComet与BitTorrent相容,Azureus更像eMule,但与其他都不相容)。
Tracker
Tracker是指运行於伺服器上的一个服务程式,也称Tracker伺服器。这个程式能够追踪到底有多少人同时在下载或上传同一个档。用户端连上Tracker伺服器,就会获得一个正在下载和上传的用户的资讯列表(通常包括IP位址、埠、用户端ID等资讯),根据这些资讯,BT用户端会自动连上别的用户进行下载和上传。
dht办事器的代码实现的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、dht办事器的代码实现的信息别忘了在本站进行查找喔。
版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;
相关推荐
- 05-09网页代码,网页代码快捷键
- 05-09舆情信息在哪里找,舆情通
- 05-06单页网站的代码(完整的网页代码)[20240506更新]
- 05-06个人主页图片代码(个人主页图片代码怎么弄)[20240506更新]
- 05-06提取微信名片代码(微信名片信息提取)[20240506更新]
- 05-06php后台权限管理代码(php管理员权限)[20240506更新]
- 05-06付费观看代码php(付费观看代码)[20240506更新]
- 05-06在线html执行代码(html怎么运行)[20240506更新]
- 05-06源代码管理资源管理器(资源管理器运行代码)[20240506更新]
- 05-06代码源软件库(程序代码库)[20240506更新]
取消回复欢迎 你 发表评论:
- 标签列表
- 最近发表
- 友情链接