在nim中提供socket程式設計的有兩個模組:nativesockets和net。 nativesockets實現的是低階的socket介面,而net則是高階的實現。
關於socket相關的知識在以前的文章:linux程式設計--套接字學習筆記 中已經講過,這裡就不在贅述。
關於跟多的nim知識你也可以看github倉庫:
例項:客戶端程式:
import net
var
client: socket
server_mes = ""
len: int
#建立客戶socket
client = newsocket()
#請求連線伺服器
client.connect("127.0.0.1", port(7000))
#通過socket進行資料傳輸
#client.send("this is from nim")
len = client.recv(server_mes, 15)
echo "from server message: ",server_mes
client.send("this is from nim")
#關閉客戶套接字:
client.close()
伺服器端程式:
import net
var
serversocket, clientsocket: socket
ipaddr = ""
client_mes = ""
server_mes = "hello, welcome!"
len: int
#為伺服器建立套接字
serversocket = newsocket()
#初始化為客戶服務的套接字
clientsocket = newsocket()
#繫結位址和埠, 第三個引數address預設為"",表示任何ip位址
serversocket.bindaddr(port(7000))
#建立乙個連線佇列,開始等待客戶進行連線
serversocket.listen(5)
while(true):
echo "server waitting"
#接受乙個連線
serversocket.acceptaddr(clientsocket, ipaddr)
echo "client from ip: ",ipaddr
#serversocket.accept(clientsocket)
#資訊傳輸
clientsocket.send(server_mes)
#clientsocket.send("two send")
len = clientsocket.recv(client_mes, 16)
echo "the received data's lenth: ", len
echo "the message is ", client_mes
#關閉套接字
clientsocket.close()
上面兩個程式是乙個普通的socket程式設計例項。這裡需要注意的是recv過程中的第三個引數指定的是讀取socket中資料的最大值,如果socket中的資料量沒有達到這個值,那麼程式將會阻塞。例如你把上面的客戶端程式改變語句:
len = client.recv(server_mes, 15) ,改變recv 中的第三個引數改為 16。再執行程式將會阻塞在那。
那麼我們怎麼知道傳送端傳送了多少位元組的資料,怎麼設定recv的引數呢? 這裡我提供一種方法,就是在傳送的資料前面用4個位元組來儲存資料的位元組數,這樣接收端就可以知道要接收多少位元組的資料了。
改進例項:
客戶端程式:
import net,strutils
var
client: socket
server_mes = "" #儲存接收伺服器傳送來的資料
client_mes = "" #客戶端向伺服器傳送的資料
client_mes_len: int #客戶傳送資料的長度
server_mes_len: int #接收伺服器的資料的長度,不包括開頭的4個位元組
#建立客戶socket
client = newsocket()
#請求連線伺服器
client.connect("127.0.0.1", port(7003))
#通過socket進行資料傳輸
#接收資料
discard client.recv(server_mes, 4)
server_mes_len = server_mes.parseint()
echo "message lenth: ", client.recv(server_mes, server_mes_len)
echo "from server message: ",server_mes
#傳送資料
client_mes = "this is from nim"
client_mes_len = client_mes.len()
#乙個套接字緩衝資料最大長度4000位元組,把資料的前4個位元組設定為傳送資料的長度
case ($client_mes_len).len()
of 1:
client_mes = "000" & $client_mes_len & client_mes
of 2:
client_mes = "00" & $client_mes_len & client_mes
of 3:
client_mes = "0" & $client_mes_len & client_mes
else:
client_mes = $client_mes_len & client_mes
client.send(client_mes)
#關閉客戶套接字:
client.close()
伺服器端程式:
import net, strutils
var
serversocket, clientsocket: socket
ipaddr = ""
client_mes = ""
server_mes = "" #傳送的資料
server_mes_len: int
client_mes_len: int
#為伺服器建立監聽套接字
serversocket = newsocket()
#初始化為客戶服務的套接字
clientsocket = newsocket()
#繫結位址和埠, 第三個引數address預設為"",表示任何ip位址
serversocket.bindaddr(port(7003))
#建立乙個連線佇列,開始等待客戶進行連線
serversocket.listen(5)
while(true):
echo "server waitting"
#接受乙個連線
serversocket.acceptaddr(clientsocket, ipaddr)
echo "client from ip: ",ipaddr
#serversocket.accept(clientsocket)
#資訊傳輸
#傳送資料
server_mes = "hi, welcome!"
server_mes_len = server_mes.len()
#乙個套接字緩衝資料最大長度4000位元組,把資料的前4個位元組設定為傳送資料的長度
case ($server_mes_len).len()
of 1:
server_mes = "000" & $server_mes_len & server_mes
of 2:
server_mes = "00" & $server_mes_len & server_mes
of 3:
server_mes = "0" & $server_mes_len & server_mes
else:
server_mes = $server_mes_len & server_mes
clientsocket.send(server_mes)
#接收資料
discard clientsocket.recv(client_mes, 4)
client_mes_len = client_mes.parseint()
echo "message lenth: ", clientsocket.recv(client_mes, client_mes_len)
echo "from client message: ",client_mes
#關閉套接字
clientsocket.close()
上面改進後的程式就不會產生資料接收阻塞現象了。
程式設計之美 NIM遊戲與NIM擴充套件遊戲的討論及解
程式設計之美上面有個nim的遊戲,規則如下 有n堆石頭,兩個人輪流從中取,一次只能在一堆中取,至少取乙個,最多把這一堆取完,取得最後乙個石頭的人勝利,問誰有必勝策略。解 設這n堆石頭的個數分別是x1,x2 xn,設f x x1 x2 x3 xn。如果f x 0則後取的獲勝,否則,先取的獲勝。證明 如...
階梯NIM和樹上NIM
有 n 個位置 1.n 每個位置上 a i 個石子。有兩個人輪流操作。操作步驟是 挑選 1.n 中任一乙個存在石子的位置 i 將至少1個石子移動至 i 1 位置 也就是最後所有石子都堆在在0這個位置 誰不能操作誰輸。求先手必勝還是必敗。問題等價於,求位置為奇數的 a i 的異或和,若異或和等於0,則...
程式設計之美 1 12 nim 2
參考 有若干堆石頭,a,b分布依次取,一次只能選擇一堆,從這堆中選擇大於0的石頭,問 1,如果最後取光石頭的人獲勝,a在什麼情況下獲勝?2,如果最後取光石頭的人失敗,a在什麼情況下獲勝?1.在規則1下,先手獲勝的情況,在規則2下先手同樣獲勝 2.規則1和規則2的取法不一樣。設當石頭出現 1,1,1,...