Nim 網路程式設計

2021-07-10 08:20:45 字數 4556 閱讀 4097

在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,...