Баррет Ли console.log( " Hi, I'm Barret, a Web Developer, try to be Excellent~ " );
войти в полноэкранный режимПодробно о WebSocket — статьи Node
20.12.2013, 13:42, Баррет Ли, 22526 прочтений, 20 комментариев,собирать, редактироватьПоднято в предыдущем постеРазличные способы веб-коммуникации, в том числе и опросы, и средства для подключения давно упомянутого HTML5. В статье будет подробно описана реализация протокола WebSocket в веб-коммуникациях.
1. Протокол веб-сокета
1 Обзор
Протокол websocket позволяет ненадежному клиентскому коду управлять удаленными хостами в контролируемой сетевой среде. Протокол состоит из рукопожатия и базового кадрирования сообщения, наложенного на TCP. Проще говоря, после ответа на рукопожатие устанавливается безопасный информационный конвейер, который явно лучше, чемПреамбулаУпомянутый поток данных iframe на основе XMLHttpRequest и длительный опрос. Протокол включает в себя два аспекта: рукопожатие и передачу данных. передача).
2. Соединение с рукопожатием
Эта часть относительно проста, как приветствие знакомого на дороге.
Client:嘿,大哥,有火没?(烟递了过去)
Server:哈,有啊,来~ (点上)
Client:火柴啊,也行!(烟点上,验证完毕)
При рукопожатии клиент сначала активно связался:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Клиент сделал строку ключа шифрования Base64 в прошлом, который выше, вы можете увидеть ключ SEC-WebSocket. После просмотра клиентского сервера встретили тихо заявил клиенту, он уже знал, кстати, также скажу привет.
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Сервер возвращает ответ Sec-WebSocket-Accept, и содержимое этого ответа формируется определенным образом. Алгоритм генерации такой:
mask = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // 这是算法中要用到的固定字符串
accept = base64( sha1( key + mask ) );
После объединения ключа и маски они обрабатываются SHA-1, а обработанные данные снова шифруются с помощью Base64. Действие разложения:
1. t = "GhlIHNhbXBsZSBub25jZQ==" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-> "GhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
2. s = sha1(t)
-> 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6
0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea
3. base64(s)
-> "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
Код состояния HTTP, возвращенный сервером выше, равен 101. Если это не 101, это означает, что рукопожатие не удалось в начале ~
Вот демонстрация рукопожатия с сервером:
var crypto = require('crypto');
require('net').createServer(function(o){
var key;
o.on('data',function(e){
if(!key){
// 握手
// 应答部分,代码先省略
console.log(e.toString());
}else{
};
});
}).listen(8000);
Код клиента:
var ws=new WebSocket("ws://127.0.0.1:8000");
ws.onerror=function(e){
console.log(e);
};
Запустите кодВыше, конечно, строка неполного кода, цель — продемонстрировать процесс рукопожатия, клиент приветствует сервер. В консоли видим:
Выглядит знакомо, но на самом деле отправляет HTTP-запрос, который мы также можем увидеть в сети браузера:
Однако протокол WebSocket не является протоколом HTTP. Заголовок HTTP был заимствован в начале проверки. После успешного подключения связь не является HTTP. Если вы мне не верите, попробуйте перехватить пакеты с помощью fiddler2 Соединение на основе TCP.
Для успешной связи с сервером должен быть ответ, см. ниже:
//服务器程序
var crypto = require('crypto');
var WS = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
require('net').createServer(function(o){
var key;
o.on('data',function(e){
if(!key){
//握手
key = e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
key = crypto.createHash('sha1').update(key + WS).digest('base64');
o.write('HTTP/1.1 101 Switching Protocols\r\n');
o.write('Upgrade: websocket\r\n');
o.write('Connection: Upgrade\r\n');
o.write('Sec-WebSocket-Accept: ' + key + '\r\n');
o.write('\r\n');
}else{
console.log(e);
};
});
}).listen(8000);
Про криптомодуль можно посмотретьофициальная документация, приведенный выше код должен быть хорошо понят. После ответа сервера клиент получает Sec-WebSocket-Accept, а затем выполняет локальную проверку. Если проверка проходит успешно, будет запущена функция onopen.
//客户端程序
var ws=new WebSocket("ws://127.0.0.1:8000/");
ws.onopen=function(e){
console.log("握手成功");
};
запустить кодможно увидеть
3. Формат фрейма данных
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
При первом взгляде на эту картинку я боюсь, что меня вырвет кровью.Если университет пересматривает курс компьютерной сети, он не должен быть незнаком с этой вещью.Протокол передачи данных должен определять длину байта и связанные с ним значения.
FIN 1bit 表示信息的最后一帧,flag,也就是标记符
RSV 1-3 1bit each 以后备用的 默认都为 0
Opcode 4bit 帧类型,稍后细说
Mask 1bit 掩码,是否加密数据,默认必须置为1 (这里很蛋疼)
Payload 7bit 数据的长度
Masking-key 1 or 4 bit 掩码
Payload data (x + y) bytes 数据
Extension data x bytes 扩展数据
Application data y bytes 程序数据
Передача каждого кадра происходит по правилам этого протокола.Зная этот протокол, анализ не составит особого труда.Я возьму его непосредственно ниже.гипокарбонат кобальтакод одноклассника.
4. Разбор и кодирование кадров данных
Код синтаксического анализа для кадра данных:
function decodeDataFrame(e){
var i=0,j,s,frame={
//解析前两个字节的基本数据
FIN:e[i]>>7,Opcode:e[i++]&15,Mask:e[i]>>7,
PayloadLength:e[i++]&0x7F
};
//处理特殊长度126和127
if(frame.PayloadLength==126)
frame.length=(e[i++]<<8)+e[i++];
if(frame.PayloadLength==127)
i+=4, //长度一般用四字节的整型,前四个字节通常为长整形留空的
frame.length=(e[i++]<<24)+(e[i++]<<16)+(e[i++]<<8)+e[i++];
//判断是否使用掩码
if(frame.Mask){
//获取掩码实体
frame.MaskingKey=[e[i++],e[i++],e[i++],e[i++]];
//对数据和掩码做异或运算
for(j=0,s=[];j<frame.PayloadLength;j++)
s.push(e[i+j]^frame.MaskingKey[j%4]);
}else s=e.slice(i,frame.PayloadLength); //否则直接使用数据
//数组转换成缓冲区来使用
s=new Buffer(s);
//如果有必要则把缓冲区转换成字符串来使用
if(frame.Opcode==1)s=s.toString();
//设置上数据部分
frame.PayloadData=s;
//返回数据帧
return frame;
}
decodeDataFrame Function
Кодирование кадра данных:
//NodeJS
function encodeDataFrame(e){
var s=[],o=new Buffer(e.PayloadData),l=o.length;
//输入第一个字节
s.push((e.FIN<<7)+e.Opcode);
//输入第二个字节,判断它的长度并放入相应的后续长度消息
//永远不使用掩码
if(l<126)s.push(l);
else if(l<0x10000)s.push(126,(l&0xFF00)>>2,l&0xFF);
else s.push(
127, 0,0,0,0, //8字节数据,前4字节一般没用留空
(l&0xFF000000)>>6,(l&0xFF0000)>>4,(l&0xFF00)>>2,l&0xFF
);
//返回头部分和数据部分的合并缓冲区
return Buffer.concat([new Buffer(s),o]);
}
encodeDataFrame Function
Некоторая детская обувь может не понимать, какие данные следует анализировать. Эта задача синтаксического анализа в основном обрабатывается сервером, а данные, отправляемые клиентом, имеют форму двоичного потока, например:
var ws = new WebSocket("ws://127.0.0.1:8000/");
ws.onopen = function(){
ws.send("握手成功");
};
запустить кодИнформация, полученная сервером, выглядит следующим образом:
Бинарный поток в формате Buffer. И проанализируйте этот двоичный поток, когда мы выводим:
//服务器程序
var crypto = require('crypto');
var WS = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
require('net').createServer(function(o){
var key;
o.on('data',function(e){
if(!key){
//握手
key = e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
key = crypto.createHash('sha1').update(key + WS).digest('base64');
o.write('HTTP/1.1 101 Switching Protocols\r\n');
o.write('Upgrade: websocket\r\n');
o.write('Connection: Upgrade\r\n');
o.write('Sec-WebSocket-Accept: ' + key + '\r\n');
o.write('\r\n');
}else{
// 输出之前解析帧
console.log(decodeDataFrame(e));
};
});
}).listen(8000);
На выходе объект с очень четкой информацией о кадре:
5. Контроль соединений
Купил пропуск выше, опкод указан, подробного описания нет,официальная документацияТакже дает таблицу:
|Opcode | Meaning | Reference |
-+--------+-------------------------------------+-----------|
| 0 | Continuation Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 1 | Text Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 2 | Binary Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 8 | Connection Close Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 9 | Ping Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
| 10 | Pong Frame | RFC 6455 |
-+--------+-------------------------------------+-----------|
decodeDataFrame анализирует данные, и результирующий формат данных:
{
FIN: 1,
Opcode: 1,
Mask: 1,
PayloadLength: 4,
MaskingKey: [ 159, 18, 207, 93 ],
PayLoadData: '握手成功'
}
Затем вы можете просмотреть его в соответствии с приведенным выше.Функция этого фрейма заключается в отправке текста, который является текстовым фреймом. Поскольку соединение основано на TCP, если вы напрямую закроете TCP-соединение, канал будет закрыт. Однако дизайн WebSocket более удобен для пользователя. Перед закрытием я передам вам привет. На стороне сервера вы можно судить об опкоде кадра:
var frame=decodeDataFrame(e);
console.log(frame);
if(frame.Opcode==8){
o.end(); //断开连接
}
Формат данных (фреймов) взаимодействия между клиентом и сервером одинаков, пока клиент отправляетws.close()
, сервер выполнит описанную выше операцию. И наоборот, если сервер отправляет тот же закрытый кадр клиенту:
o.write(encodeDataFrame({
FIN:1,
Opcode:8,
PayloadData:buf
}));
Клиент будет включать соответствующие функции, такие взаимодействия по-прежнему правила имеют моменты, не склонны к ошибке.
2. Вопросы, требующие внимания
1. WebSocket URIs
Многие люди могут знать толькоws://text.com:8888
, но на самом деле адрес протокола веб-сокета может добавить путь и запрос.
ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
Если используется протокол wss, URI будет подключен безопасным образом. Здесь wss не чувствителен к регистру.
2. "Лишняя" часть соглашения (Tucao)
Запрос рукопожатия содержит поле Sec-WebSocket-Key, которое может быть замечено проницательным человеком как подключение по вебсокету, и метод шифрования этого поля также фиксируется на сервере.Если кто-то захочет вас взломать, он не будет слишком трудно.
Затем есть маска MaskingKey, так как она принудительно шифруется (Mask is 1 означает шифрование, а метод шифрования — обработка XOR между MaskingKey и PayLoadData), нужно ли разработчикам разбираться с этой штукой? Разве не было бы достаточно инкапсулировать его прямо внутри?
3. Связь с TCP и HTTP
Протокол WebSocket является протоколом на основе TCP, то есть, когда ссылка рукопожатия связана с HTTP (отправляется HTTP-запрос), сервер переключает запрос на протокол веб-сокета (обновление). websocket использует порт 80 в качестве порта подключения к веб-сокету по умолчанию, а веб-сокет работает на порту 443.
3. Ссылки
- tools.I ETF.org/HTML/RFC645… web standard - The WebSocket Protocol
- Woohoo. Мой 3.org/TR/Web Soc может… W3.ORG - WebSockets
4. Отдельное спасибо
Спасибо еще разгипокарбонат кобальтаРазговаривал со мной несколько часов :), часть кода узла в этой статье взята из его блога.
В следующий раз я буду использовать php в качестве фона, чтобы объяснить соответствующие знания о веб-сокетах.
награда
Уведомление об авторских правах: Attribution-Non-Commercial-No Derivatives 3.0 International (CC BY-NC-ND 3.0)
- Классификация:HTML[5]+CSS[3],JavaScript,Others
- Этикетка:javascript, communication, websocket
-
#1-й этаж simonleung 2013-12-20 14:31
websocket начинает рукопожатие с событием http onupgrade
Не использовать ondata сети.
узел будет .org/API/HTTP. Контракт... Поддержка(0) против (0) -
#2-ой этаж[арендодатель] Barret Lee 2013-12-20 14:37
@ simonleung
Данные сети находятся на более низком уровне, чем при обновлении http.
От описания протокола вебсокета до отображения результатов теста нет никаких проблем.Поддержка(0)против (0) http://pic.cnblogs.com/face/387325/20150805014702.png -
#3-й этаж Nima Fan Ye. 2013-12-20 21:21
Очень хорошо написано, восхищаюсьПоддержка(0)против (0) http://pic.cnblogs.com/face/395638/20140818132358.png -
#4-й этаж логический 2013-12-20 22:04
Я не знаю, почему, когда я использую node-webkit, но соединение очень медленное, когда количество соединений больше 100 (более 100).Поддержка(0)против (0) http://pic.cnblogs.com/face/u17705.jpg -
#5-й этаж второй брат Тони 2013-12-21 11:56
ищу эту статьюПоддержка(0)против (0) http://pic.cnblogs.com/face/348990/20160120104927.png -
#6 этаж Ace8793 2013-12-22 22:00
mark Поддержка(0)против (0) http://pic.cnblogs.com/face/377458/20161107194642.png -
#7 этаж flyher 2013-12-23 08:26
@BarretLee
Хорошая статья, увидела только в понедельник, реально поздно видеться, сохраните на будущее.Поддержка(0)против (0) http://pic.cnblogs.com/face/u218282.jpg -
№8 Этаж dotNetDR_ 2013-12-24 15:26
хорошо~Поддержка(0)против (0) http://pic.cnblogs.com/face/u59691.jpg -
№9 Этаж исчисление г 2013-12-26 21:07
Отлично, выучил!Поддержка(0)против (0) -
№10 этаж это Смурфики 2014-03-26 20:08
УчитьПоддержка(0)против (0) -
№11 Этаж титульный лист 2014-04-02 10:54
Уважаемый, картинаПоддержка(0)против (0) -
#12F[арендодатель] Barret Lee 2014-04-02 16:38
@титульный лист
Я в порядке здесь, вы можете обновить его?Поддержка(0)против (0) http://pic.cnblogs.com/face/387325/20150805014702.png -
№13 Этаж mcarzx 2014-04-21 17:46
1. t = "GhlIHNhbXBsZSBub25jZQ==", в начале строки отсутствует буква d
2. console.log(crypto.createHash('sha1').update('dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest('sha1')); // Вывод:, в отличие от вашего, с 0x впереди, как вы его получили?
3. Часть декодирования: if(frame.PayloadLength==126) frame.length=(e[2]
4, кодирующая часть: s.push (126, (l & 0xff00) >> 2, L & 0xFF); Где >> 2, кажется >> 8. Следующая строка аналогична.Поддержка(0)против (0) -
№ 14 этаж Маста 2014-11-12 21:03
Простите, брат усат, как postMessage общается между доменами, онлайн-поиск сложен, но я в этом не разбираюсьПоддержка(0)против (0) -
№15 Этаж[арендодатель] Barret Lee 2014-11-12 21:51
@Маста
Страница A взаимодействует с iframe B, который является чужим для страницы.
И postMessage, и onmessage запускаются для одного и того же оконного объекта.
Получите дескриптор окна B в A, используйте B.contentWindow.postMessage для отправки информации в B, а B имеет прослушиватель onmessage.
Принцип отправки сообщения от b до a это то, что б Получите ручку окна, используйте a.parent.postmessage для отправки информации в A, а A имею прослушиватель OnMessage.
Очистить принцип, он должен быть одинаковым окном для отправки информации для себя, но мы получаем дескриптор окна в другом окне, например iframe.contentwindow, или iframe получает окно окна службы.
Если вы этого не понимаете, это не потому, что у вас проблемы с пониманием, а потому, что вы недостаточно хорошо поняли эти понятия. Если вы все еще не понимаете, прочтите сами MSDN/MDN. документация.Поддержка(0)против (0) http://pic.cnblogs.com/face/387325/20150805014702.png -
№16 Этаж riskers 2015-03-04 14:24
После объединения ссылочного ключа и маски они обрабатываются SHA-1, а обработанные данные снова шифруются с помощью Base64.
base64 - это метод кодирования, а не шифрованиеПоддержка(0)против (0) -
№17 Этаж CoderZ 2015-06-29 12:05
Простите, брат усатый, только что понял, что ваш метод удобен в применении. Я снова посмотрел на socket.io, но обнаружил, что в заголовке запроса socket.io нет информации о веб-сокете, но он основан на веб-сокете, я не знаю, почему?Поддержка(0)против (0) http://pic.cnblogs.com/face/579305/20131227132708.png -
№18 Этаж Пинавший Человек.Орз 2015-07-20 15:55
mark Поддержка(0)против (0) http://pic.cnblogs.com/face/520225/20131008114345.png -
№19 Этаж gongmaolan123 2017-01-13 12:59
GoEasy web: три шага для простой реализации push-уведомлений в реальном времени
1. Представьте goeasy.js
2. Клиентская подписка,
Var goeasy = new GoEasy({ключ приложения:'ваш ключ приложения'});
goousy.subscribe (канал: "Ваш канал", OnMessage: Функция (сообщение)
{оповещение('полученное сообщение'+ message.content)}
)
3. Три метода нажатия
Javascript: goeasy.publish({channel:'ваш канал', message:'ваше сообщение о публикации'});
Java SDK:
GoEasy goeasy = новый GoEasy("ключ приложения");
goeasy.publish("ваш канал", "ваше сообщение");
RestAPI: полегче.IO/полегче/водопад…
三步轻松实现web推送及接收。 Официальный сайт:goeasy.io, документация завершенаПоддержка(0)против (0) -
#20F38077282017/10/11 18:57:09 линукс, 2017-10-11 18:57
@ simonleung
Модуль http написан на основе сети, а в сети нет этого события.Поддержка(0)против (0)
【Событие】Alibaba Cloud Double 11 Event начинает разогрев облачного сервера со скидкой 20% в течение ограниченного времени
[Расследование] Немедленно примите участие в отмеченном призом исследовании, вы на самом деле программист Цзянцзы!
[Рекомендуется] Быстрый старт Vue.js 2.x, множество эффективных практических примеров
Последние ИТ-новости:
· Рост технического образования
· Верховный суд США отклонил апелляцию Samsung и должен выплатить Apple 120 миллионов долларов в качестве компенсации
· Черная технология Adobe выглядит более химической, чем таблица химических элементов
· Дисбаланс в индустрии экспресс-доставки: штраф за условное депонирование приводит к нехватке рабочей силы, новички берутся за работу без обучения
· Почему хорошая репутация мобильных телефонов Sony не может принести хороших продаж?
» больше новостей... Последние статьи базы знаний:
· 3+10 привычек, улучшающих качество жизни программиста
· 10 принципов кодирования НАСА
· Почему ты проходишь так много тренировок и все равно остаешься посредственным?
· Письмо начинающему фронтенд-инженеру
· Практические принципы проектирования виртуального частного облака VPC
» Другие статьи базы знаний...
Переезд блога: http://barretlee.com
шарф:@Barret, Ли Цзин, усы Brother Brother Channel общественное число:усатый брат😃Гитхаб:barretlee
Статус: Taobao UED-F2E и медленные осадки
Отказ от ответственности: Все статьи без специальных указаний являются оригинальными.Поскольку старый и неправильный контент часто модифицируется или удаляется, пожалуйста, указывайте адрес источника для перепечатки. Статьи являются личным мнением и не представляют компанию. ты первыйпосетитель, добро пожаловать~ Никнейм:Barret Lee
Возраст сада:5 лет 7 месяцев
честь:Рекомендуемый блог
вентилятор:2731
Сфокусируйся на:20 +Добавить подпискуПоиск статьи: Go!
последнее эссе
- Краткое описание настройки Nginx
- Расскажите о моем росте в Али
- Демистификация 0,1 + 0,2 != 0,3
- Как быть хорошим стажером
- Расскажите о моем техническом росте за последние три года
- Работать пять лет и повторять работу первого года следующие четыре года?
- ECMAScript 6 Грамотность
- Текущий внешний интерфейс также имеет возможность сервера
- Кратко опишите процесс работы OAuth 2.0
- Инвентаризация передовых технологий за последние годы и направления развития технологий в 2016 г.
- Отладка кода и настройка производительности для NodeJS
- Запущено новое приложение Snippet
- Какова ситуация с отравлением программного обеспечения Apple, упомянутая в последние два дня?
- Блог был перенесен на http://barretlee.com/entry/ и иногда публикуется здесь.
последний комментарий
- Re: подробнее о websocket - php статьи
узнал, спасибо -- штормовой перевал - Re: Расскажите о моем росте в Али.
Маленькая Борода, мы встретимся~ -- wbxjiayou - Re: подробнее о WebSocket - статьи Node
@simonleung Модуль http написан на основе сети, а в сети нет этого события. --Линукс, - Re: сбор и мониторинг журналов исключений внешнего кода
Даже исходный код браузера убран, мне должно понравиться -- -облако- - Re: Реализация цепочки вызовов javascript.
Ты великолепен! Мне этого мало, мне еще нужно много работать. -- обречены на злоупотребление кодом
Архив эссе
- ноябрь 2016 г. (1)
- Октябрь 2016 (3)
- июль 2016 (3)
- Февраль 2016 (1)
- Январь 2016 (2)
- октябрь 2015 г. (1)
- Сентябрь 2015 (4)
- август 2015 (6)
- июль 2015 г. (1)
- Май 2015 (2)
- Апрель 2015 (4)
- декабрь 2014 г. (1)
- ноябрь 2014 г. (1)
- октябрь 2014 г. (1)
- сентябрь 2014 г. (1)
- август 2014 (4)
- июль 2014 г. (1)
- Май 2014 (6)
- Апрель 2014 (4)
- март 2014 г. (8)
- Февраль 2014 (7)
- Январь 2014 (4)
- Декабрь 2013 (6)
- ноябрь 2013 г. (5)
- октябрь 2013 г. (2)
- сентябрь 2013 г. (3)
- август 2013 г. (3)
- июль 2013 г. (3)
- июнь 2013 г. (6)
- Май 2013 (5)
- Апрель 2013 (12)
- март 2013 г. (6)
javascript
- ajaxian
- alistapart
- developer.mozilla.org
- diveintohtml5
- ecmascript
- Eric Meyer
- es5
- nanto
- perfectionkills
- ppk
- sitepoint
- webfx
- Документация для отдела webkit
- Создание высокопроизводительного веб-сайта
календарь
|
||||||
день | один | два | три | Четыре | Пятерки | шесть |
---|---|---|---|---|---|---|
29 | 30 | 31 | 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
классификация эссе
- AJAX(5)
- Cross Domain(3)
- Design patterns(4)
- DOM(2)
- Спецификация ECMAScript (8)
- HTML[5]+CSS[3](17)
- JavaScript(62)
- Javascript plugins(7)
- jQuery and plugins(1)
- Linux(2)
- Node(5)
- Others(52)
- PHP(4)
- translation(4)
Рекомендуемая таблица лидеров
- 1. Глядя на внешний интерфейс из окна входа в систему (136)
- 2. Инвентаризация передовых технологий за последние годы и направления развития технологий в 2016 г. (85)
- 3. Сбор и мониторинг журналов исключений внешнего кода (63)
- 4. Три месяца на Али (62)
- 5. Принципы асинхронного программирования на JavaScript (43)
- 6. Принцип шаблонизатора JavaScript, несколько строк кода (36)
- 7. Почему не вступает в силу модификация Hosts?Это кэш DNS? (29)
- 8. Как сделать код JavaScript более семантичным (25)
- 9. Детали WebSocket — узел (23)
- 10. Многофайловая загрузка JavaScript(23)
Читать таблицу лидеров
- 1. Подробно объясните websocket-php (40514)
- 2. Глядя на внешний интерфейс из окна входа в систему (29573)
- Реализация и приложение 3. PJAX (27324)
- 4. Запретить браузерам показывать оповещения для HTTP-запросов на https-страницах (25059).
- 5. Принцип работы шаблонизатора JavaScript, несколько строк кода (23234)
- 6. Детали WebSocket — узел (22523)
- 7. Сбор и мониторинг журнала исключений внешнего кода (21883)
- 8. Многофайловая загрузка JavaScript (21859)
- 9. Принципы асинхронного программирования JavaScript (17802)
- 10. Почему модификация Хостов не вступает в силу?Это кеш DNS? (16597)
css
friends
- Aaron
- Rss Barret Lee
- guangwong
- Rss гипокарбонат кобальта
- Haitou.com
- Команда Tencent Alloy
- Нефритовая мордочка рыбки
- Rss Чжан Синьсюй
Tools
- cleancss
- css-validator
- proxyie.cn/
- jsbeautifier
- JSLint
- Packer-Decoder
- regexper
- RunJS
- stackoverflow
- User Agent
- Форматировать HTML онлайн
- Изучаем интерфейсную архитектуру
- Исследование ECMAScript6
- Ecma-262 Peruse
- Микрообмен
- Библиотека анимации
- →_→Работа ←_ ←
- Стажер-стажер Taobao UED, где ваше резюме? Отправьте его сюда на barret.china@gmail.com~
- Совсем недавноМикрообмен
- ток201Общий чат 0