1. 如何在客戶端上建立一個Socket與伺服器端連接,包括連接的函數
ClientSocket組件為客戶端組件。它是通信的請求方,也就是說,它是主動地與伺服器端建立連接。
ServerSocket組件為伺服器端組件。它是通信的響應方,也就是說,它的動作是監聽以及被動接受客戶端的連接請求,並對請求進行回復。
ServerSocket組件可以同時接受一個或多個ClientSocket組件的連接請求,並與每個ClientSocket組件建立單獨的連接,進行單獨的通信。因此,一個伺服器端可以為多個客戶端服務。
設計思路
本例包括一個伺服器端程序和一個客戶端程序。客戶端程序可以放到多個計算機上運行,同時與伺服器端進行連接通信。
本例的重點,一是演示客戶端與伺服器端如何通信;二是當有多個客戶端同時連接到伺服器端時,伺服器端如何識別每個客戶端,並對請求給出相應的回復。為了保證一個客戶端斷開連接時不影響其它客戶端與伺服器端的通信,同時保證伺服器端能夠正確回復客戶端的請求,在本例中聲明了一個記錄類型:
type
client_record=record
CHandle: integer; //客戶端套接字句柄
CSocket:TCustomWinSocket; //客戶端套接字
CName:string; //客戶端計算機名稱
CAddress:string; //客戶端計算機IP地址
CUsed: boolean; //客戶端聯機標志
end;
利用這個記錄類型數據保存客戶端的信息,同時保存當前客戶端的連接狀態。其中,CHandle保存客戶端套接字句柄,以便准確定位每個與伺服器端保持連接的客戶端;Csocket保存客戶端套接字,通過它可以對客戶端進行回復。Cused記錄當前客戶端是否與伺服器端保持連接。
下面對組件ServerSocket和ClientSocket的屬性設置簡單說明。
ServerSocket的屬性:
· Port,是通信的埠,必須設置。在本例中設置為1025;
· ServerTypt,伺服器端讀寫信息類型,設置為stNonBlocking表示非同步讀寫信息,本例中採用這種方式。
· ThreadCacheSize,客戶端的最大連接數,就是伺服器端最多允許多少客戶端同時連接。本例採用默認值10。
其它屬性採用默認設置即可。
ClientSocket的屬性:
· Port,是通信的埠,必須與伺服器端的設置相同。在本例中設置為1025;
· ClientType,客戶端讀寫信息類型,應該與伺服器端的設置相同,為stNonBlocking表示非同步讀寫信息。
· Host,客戶端要連接的伺服器的IP地址。必須設置,當然也可以在代碼中動態設置。
其它屬性採用默認設置即可。
2. 如何添加資料庫
以添加Socket資料庫批量列印為例子來進行操作;
根據標簽紙實際尺寸設置紙張尺寸,然後點擊上方工具欄中的資料庫設置圖標,在彈出窗口中點擊「添加」選擇最下方的「Socket數據源」:
在連接Socket資料庫時還需注意以下幾個方面:
1、該伺服器上提前應運行對應的Socket通訊響應的服務程序;
2、當列印軟體提交數據獲取指令(get01)時,該服務程序應及時返回一條列印數據;
3、當列印軟體提交的指令有「##」前綴時,則為預覽數據請求,服務程序視情況進行響應。
3. 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
})
}
});