導航:首頁 > 編程語言 > nodejssocket編程

nodejssocket編程

發布時間:2023-08-04 07:12:36

A. nodejs 怎麼和exe進行socket通信

完成 Sever --> Client 的單向通訊。

[javascript] view plain
// Sever --> Client 的單向通訊
var net = require('net');

var chatServer = net.createServer();

chatServer.on('connection', function(client) {
client.write('Hi!\n'); // 服務端向客戶端輸出信息,使用 write() 方法
client.write('Bye!\n');

client.end(); // 服務端結束該次會話
});

chatServer.listen(9000);
客戶端可以是系統自帶的 Telnet:

[plain] view plain
telnet 127.0.0.1 9000
執行 telnet 後,與服務點連接,反饋 Hi! Bye! 的字元,並立刻結束服務端程序終止連接。如果我們要服務端接到到客戶端的信息?可以監聽 server.data 事件並且不要中止連接(否則會立刻結束無法接受來自客戶端的消息):

[javascript] view plain
// 在前者的基礎上,實現 Client --> Sever 的通訊,如此一來便是雙向通訊
var net = require('net');
var chatServer = net.createServer(),
clientList = [];

chatServer.on('connection', function(client) {
// JS 可以為對象自由添加屬性。這里我們添加一個 name 的自定義屬性,用於表示哪個客戶端(客戶端的地址+埠為依據)
client.name = client.remoteAddress + ':' + client.remotePort;
client.write('Hi ' + client.name + '!\n');
clientList.push(client);
client.on('data', function(data) {
broadcast(data, client);// 接受來自客戶端的信息
});
});
function broadcast(message, client) {
for(var i=0;i<clientList.length;i+=1) {
if(client !== clientList[i]) {
clientList[i].write(client.name + " says " + message);
}
}
}
chatServer.listen(9000);

這里要說明一下的是,不不同操作系統對埠范圍的限制不一樣,有可能是隨機的。
那麼上面是不是一個完整功能的代碼呢?我們說還有一個問題沒有考慮進去:那就是一旦某個客戶端退出,卻仍保留在 clientList 裡面,這明顯是一個空指針(NullPoint)。如果是在這樣的話我們寫程序太脆弱了,能不能更健壯一些?——請接著看。
首先我們簡單地把 client 從數組 clientList 中移除掉。完成這工作一點都不困難。Node TCP API 已經為我們提供了 end 事件,即客戶端中止與服務端連接的時候發生。移除 client 對象的代碼如下:

[javascript] view plain
chatServer.on('connection', function(client) {
client.name = client.remoteAddress + ':' + client.remotePort
client.write('Hi ' + client.name + '!\n');

clientList.push(client)

client.on('data', function(data) {
broadcast(data, client)
})

client.on('end', function() {
clientList.splice(clientList.indexOf(client), 1); // 刪除數組中的制定元素。這是 JS 基本功哦~
})
})
但是我們還不敢說上述代碼很健壯,因為一旦 end 沒有被觸發,異常仍然存在著。下面我們看看解決之道:重寫 broadcast():

[javascript] view plain
function broadcast(message, client) {
var cleanup = []
for(var i=0;i<clientList.length;i+=1) {
if(client !== clientList[i]) {

if(clientList[i].writable) { // 先檢查 sockets 是否可寫
clientList[i].write(client.name + " says " + message)
} else {
cleanup.push(clientList[i]) // 如果不可寫,收集起來銷毀。銷毀之前要 Socket.destroy() 用 API 的方法銷毀。
clientList[i].destroy()
}

}
} //Remove dead Nodes out of write loop to avoid trashing loop index
for(i=0;i<cleanup.length;i+=1) {
clientList.splice(clientList.indexOf(cleanup[i]), 1)
}
}
TCP API 中還提供一個 error 事件,用於捕捉客戶端的異常:

[javascript] view plain
client.on('error', function(e) {
console.log(e);
});

Node 網路編程的 API 還豐富,此次僅僅是個入門,更多的內容請接著看,關於瀏覽器 Socket 應用。
Socket.IO
前面說到,瀏覽器雖然也屬於客戶端的一種,但僅支持「單工」的 HTTP 通訊。有見及此,HTML5 新規范中推出了基於瀏覽器的 WebSocket,開發了底層的介面,允許我們能進行 更強大的操作,超越以往的 XHR。
如第一個例子那般,我們無須第三方框架就可以直接與 Node TCP 伺服器 進行 Socket 通訊。
但我們又要認清一個事實,不是每個瀏覽器都可以順利支持 WebSocket 的。於是 Socket.IO (http://socket.io)出現了,它提供了不支持 WebSocket 時候的降級支持,同時使得一些舊版本的瀏覽器也可以「全雙工」地工作。優先使用的順序如下:
WebSocket
Socket over Flash API
XHR Polling 長連接
XHR Multipart Streaming
Forever Iframe
JSONP Polling

經過封裝,我們可以不探究客戶端使用上述哪一種技術達致「全雙工」;而我們編寫代碼時,亦無論考慮哪種放法,因為 Socket.IO 給我們的 API 只有一套。了解 Socket.IO 其用法就可以了。

先在瀏覽器部署 Socket.IO 的前端代碼:

[html] view plain
<!DOCTYPE html>
<html>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
// 當服務端發送一條消息到客戶端,message 事件即被觸發。我們把消息在控制台列印出來
socket.on('message', function(data){ console.log(data) })
</script>
</body>
</html>
服務端 Node 代碼:

[javascript] view plain
var http = require('http'),
io = require('socket.io'),
fs = require('fs');

// 雖然我們這里使用了同步的方法,那會阻塞 Node 的事件循環,但是這是合理的,因為 readFileSync() 在程序周期中只執行一次,而且更重要的是,同步方法能夠避免非同步方法所帶來的「與 SocketIO 之間額外同步的問題」。當 HTML 文件讀取完畢,而且伺服器准備好之後,如此按照順序去執行就能讓客戶端馬上得到 HTML 內容。
var sockFile = fs.readFileSync('socket.html');

// Socket 伺服器還是構建於 HTTP 伺服器之上,因此先調用 http.createServer()
server = http.createServer();
server.on('request', function(req, res){
// 一般 HTTP 輸出的格式
res.writeHead(200, {'content-type': 'text/html'});
res.end(sockFile);
});

server.listen(8080);

var socket = io.listen(server); // 交由 Socket.io 接管

// Socket.io 真正的連接事件
socket.on('connection', function(client){
console.log('Client connected');
client.send('Welcome client ' + client.sessionId); // 向客戶端發送文本
});
當客戶端連接時,服務端會同時出發兩個事件:server.onRequest 和 Socket.onConnection。它們之間有什麼區別呢?區別在於 Socket 的是持久性的。
多個 Socket 連接,先是客戶端代碼:
[html] view plain
<!DOCTYPE html>
<html>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var upandrunning = io.connect('http://localhost:8080/upandrunning');
var weather = io.connect('http://localhost:8080/weather');
upandrunning.on('message', function(data){
document.write('<br /><br />Node: Up and Running Update<br />');
document.write(data);
});
weather.on('message', function(data){
document.write('<br /><br />Weather Update<br />');
document.write(data);
});
</script>
</body>
</html>
服務端代碼:
[javascript] view plain
var sockFile = fs.readFileSync('socket.html');

server = http.createServer();
server.on('request', function(req, res){
res.writeHead(200, {'content-type': 'text/html'});
res.end(sockFile);
});

server.listen(8080);

var socket = io.listen(server);

socket.of('/upandrunning')
.on('connection', function(client){
console.log('Client connected to Up and Running namespace.');
client.send("Welcome to 'Up and Running'");
});

socket.of('/weather')
.on('connection', function(client){
console.log('Client connected to Weather namespace.');
client.send("Welcome to 'Weather Updates'");
});

如上代碼,我們可以劃分多個命名空間,分別是 upandrunning 和 weather。

B. nodejs 怎麼把socket數據寫入資料庫

先說下我對socket.io的理解,websocket更像是開啟了一個埠服務,來監視過往的通訊。所以我們可以依賴於當前站點80埠啟socket服務,也可以放於其他埠上,比如:

1

require('socket.io').listen(3000);

這樣就是監視3000埠了,由於我用的免費伺服器,沒有許可權打開其他埠,所以,我還是使用80了,由於80已經被express使用了,所以我只好在express使用的時候傳進來了。

var server = http.createServer(app);

var socket = require('./socket/msg')(server);

然後 我在msg.js里是這樣寫的
var db = require('../db/mysql');
var sio = require('socket.io');
var IO = function(server) {
var io = sio.listen(server)

這樣就和諧了,db是創建mysql連接的方法,不在本節內容里,略。
在socket.io里是這樣的,首先創建一個io通道的連接,然後監視裡面的socket的事件,nodejs是事件驅動嘛。代碼如下:

io.on('connection', function(socket) {
console.log('a user connected.');
socket.on('disconnect', function() {
console.log('user disconnected.');
});
})

這時只要有用戶連接上,就會進入connection中了,然後它的參數是個socket,如果是公聊,我們可以直接用

1

io.emit('chat message', {});

這種形式了。但我們這里是私聊,所以我們要臨時的把這個socket對象保存在全局裡,供與你私聊的對象使用找到你的socket,很繞口,其實這里的私聊,不算完全的點對點,它還是經過了伺服器的,消息傳給伺服器,伺服器再找到你要傳達給的那個人的socket對象,發給他。這就是整個的過程了。這里我使用的是一個類數組對象來存儲的.
var users = {},
usocket = {};
socket.on('user join', function(data) {
users[username] = username;
usocket[username] = socket;
})

由於我這里需要用戶名登錄,所以我就把用戶名作為了唯一的標識,這里用類數組的形式的好處就是我不用循環也能夠很快的找到它。再我給A發送私聊時,我會先在這個uscoket裡面找到它,然後調用它的emit。
function sendUserMsg(data) {
if (data.to in usocket) {
console.log('================')
console.log('to' + data.to, data);
usocket[data.to].emit('to' + data.to, data);
usocket[data.user].emit('to' + data.user, data);
console.log('================')
}
}

這里我emit了兩次的原因是,我發給對方消息的同時,我自己也要收到這個消息,然後把它顯示出來,為什麼這樣?其一,介面統一了,聊天里的內容全是伺服器過來的,其二,證明我發送成功了。
然後我在客戶端監聽時,也用我自己的用戶名起了一個to+用戶名的事件監聽。

socket.on('to' + user, function(data) {
//console.log(data);
formatMsg(data);
})

這樣,不管是我發的消息,還是我收到消息,都會進入這個事件了。最後,在用戶離開的時候別忘記delete掉這個對象。

socket.on('disconnect', function() {
console.log('disconnect')
if (username) {
counter--;
delete users[username];
delete usocket[username];
if (home.name == username) {
homeLeave(username);
}
sendmsg({
type: 0,
msg: "用戶<b>" + username + "</b>離開聊天室",
counter: counter,
users: users
})
}
});

C. Nodejs的WebSocket模塊怎麼設置連接超時時間

在建立socket連接時可以很容易設置socket通信的發送和接收超時時間,但是在建立socket通信時,如果是Win98系統,則如果連接失敗,則程序會一直等待在哪裡,Windows2000默認超時時間是30秒,當然,這個超時時間不算長,但是加入我們要循環掃描一系列埠並且建立連接的話,總的等待時間就會讓人忍受不了,下面就以delphi為例進行說明,如何在建立socket的時候設置其超時時間:
//連接,發送和接收時間都設為2秒
SctTimeOut := 2000;
//設置接收數據通信超時
setsockopt(hSock,SOL_SOCKET,SO_RCVTIMEO,@SctTimeOut,SizeOf(Integer));
//設置發送數據通信超時
setsockopt(hSock,SOL_SOCKET,SO_SNDTIMEO,@SctTimeOut,SizeOf(Integer));
//首先,設置通訊為非阻塞模式
dwArg := 1;
RecvLen := ioctlsocket(hSock,FIONBIO,dwArg);
//其次,連接伺服器
ZeroMemory(@addr, sizeof(addr));
addr.sin_family := AF_INET;
addr.sin_addr.S_addr := inet_addr(pchar(SvrIP));
addr.sin_port := htons(Strtoint(SvrPort));
RecvLen := 0;
RecvLen := connect(hSock, addr, sizeof(addr));
//再次,設置連接超時時間為2秒
tmOut.tv_sec := 2;
tmOut.tv_usec := 0;
FD_ZERO(recvSet);
FD_SET(hSock, recvSet);

RecvLen := select(0, @recvSet, @recvSet, nil, @tmOut);
//連接失敗,報錯誤信息
if (RecvLen = 0) or (RecvLen = SOCKET_ERROR) then
begin
ErrMsg := '連接伺服器失敗!';
exit;
end;
//最後,設置通訊為阻塞模式
dwArg := 0;
RecvLen := ioctlsocket(hSock,FIONBIO,dwArg);
//end modify

D. nodejs socket 怎麼檢測客戶端主動斷開連接

根據 https://github.com/LearnBoost/socket.io-spec 文檔中說是在transport連接 (就是TCP)Close後再等一段時間(15秒,可配置)釋放資源。我們知道一般TCP 不會輕易Close,網站沒數據,可能連接一直存在著。
所以有兩種思路,一個是自己在在Scoket.io的業務層設置定時器,超過一段時間無業務數據,釋放socket.io的資源。另一種就是把TCP連接超時時間設短,不過要注意socket.io的socket不是node.js的socket,可以參考以下代碼:
io.sockets.on(『connection』, function (socket) {
socket.manager.transports[socket.id].socket.setTimeout(15000);
//…
}
如果client關閉後,大約15+15秒之後會釋放資源。

閱讀全文

與nodejssocket編程相關的資料

熱點內容
電子資料文件有哪些 瀏覽:241
猥瑣貓表情教程 瀏覽:599
android音頻文件格式 瀏覽:458
漫畫臉app哪裡可以下載 瀏覽:959
購買歡樂升級歡樂豆 瀏覽:282
學習智能機器人用什麼編程最好 瀏覽:655
蘋果手機如何管控app 瀏覽:633
mn文件夾 瀏覽:590
安卓平板通用刷機包下載 瀏覽:751
安卓獲取內部存儲路徑 瀏覽:880
寫代碼兩台顯示器 瀏覽:327
unitypackage壓縮文件 瀏覽:493
奕心安卓 瀏覽:563
使用土地的有關證明文件包含哪些 瀏覽:493
數據標注哪裡可以接 瀏覽:482
在家自學編程下什麼學 瀏覽:705
最近很火的app軟體是什麼軟體 瀏覽:862
ai文字工具 瀏覽:157
蘭博玩游戲路徑怎麼選擇正確文件 瀏覽:972
淘寶直通車恢復老版本 瀏覽:510

友情鏈接