服务器端
#singleinstance force OnExit, exit ;ip和端口 Network_Address = 0.0.0.0 Network_Port = 1000 ;游戏数据 QA := [] QA.insert({"Question":"一天有多少个小时","Answer":"A","A":"24个小时","B":"12个小时","C":"30个小时","D":"365个小时"}) QA.insert({"Question":"中国居民用电的电压是多少伏","Answer":"D","A":"110V","B":"48V","C":"380V","D":"220V"}) QA.insert({"Question":"林俊杰是哪里人","Answer":"C","A":"台湾","B":"香港","C":"新加坡","D":"马来西亚"}) QA.insert({"Question":"一杯水测试PH值为8表示","Answer":"B","A":"酸性","B":"碱性","C":"辣的","D":"有毒"}) ;创建窗口以接收数据 Gui, add, Edit, x0 y0 w400 h200 vshow, Gui, add, Button, x0 y200 w400 h20 gchange, 换题 gui, add, text, x400 y0 w100 h20, 以下玩家加入: gui, Add, ListBox, x400 y20 w100 h200 vlist gui, Show, , 答题游戏局域网服务器 ;准备传入连接 socket := PrepareForIncomingConnection(Network_Address, Network_Port) if socket = -1 ExitApp Process, Exist NotificationMsg := 0x5555,FD_Read := 1,FD_CLOSE := 32,FD_CONNECT := 20 ;消息号 大于0x1000;当消息可以读取时接收;当连接关闭后时接收 ;设置接收消息的函数 OnMessage(NotificationMsg, "ReceiveData") ;设置接收关联 if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", A_ScriptHwnd, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT) { MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") ExitApp } ;循环获取新连入客户端 user := [] i=1 Loop { VarSetCapacity(SocketAddress, SizeOfSocketAddress:=16) ;Socket连接 conectioncheck%i% := DllCall("Ws2_32\accept", "UInt", socket, "UInt", &SocketAddress, "Int*", SizeOfSocketAddress) if conectioncheck%i% != -1 { ;该客户端连接对象为conectioncheck%i% 发送数据时需要 ;客户端IP:端口 xxx.xxx.xxx.xxx:xxxx peername := DllCall("Ws2_32\inet_ntoa", "uint", NumGet(SocketAddress,4), "str") . ":" NumGet(SocketAddress,2,"ushort") user["" peername] := conectioncheck%i% ;发送欢迎信息 ;SendData(conectioncheck%i%,"欢迎" peername) ;添加到列表 list = for k,v in user list .= "|" k GuiControl, , list, % list i++ } sleep 500 } return ;换题 change: SendText = Clean gosub, sendall ct = 0 for k in QA ct++ Random, Q_id, 1, % ct SendText := QA[Q_id]["Question"] "?nA:" QA[Q_id]["A"] "
tB:" QA[Q_id]["B"] "tC:" QA[Q_id]["C"] "
tD:" QA[Q_id]["D"] GuiControl, , show, % "当前题目:n" SendText "
n答案:" QA[Q_id]["Answer"] gosub, sendall return ;给所有客户端发消息 sendall: Loop %i% { SendData(conectioncheck%A_Index%,SendText) } SendText= return ;准备传入连接函数 PrepareForIncomingConnection(IPAddress, Port) { VarSetCapacity(wsaData, 32) result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)
if ErrorLevel
{
MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
return -1
}
if result
{
MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
return -1
}
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
if socket = -1
{
MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
return -1
}
SizeOfSocketAddress = 16
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
InsertInteger(2, SocketAddress, 0, AF_INET) ; sin_family
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2) ; sin_port
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4) ; sin_addr.s_addr
if DllCall("Ws2_32\bind", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
{
MsgBox % "bind() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
return -1
}
if DllCall("Ws2_32\listen", "UInt", socket, "UInt", "SOMAXCONN")
{
MsgBox % "LISTEN() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
return -1
}
return socket
}
;接收消息函数
ReceiveData(wParam, lParam)
{
Critical
global ShowRecieved
socket := wParam
ReceivedDataSize = 4096
Loop
{
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
if ReceivedDataLength = -1
{
WinsockError := DllCall("Ws2_32\WSAGetLastError")
if WinsockError = 10035
return 1
if WinsockError <> 10054
;MsgBox % "recv() indicated Winsock error " . WinsockError
return WinsockError
}
if ReceivedData
deal(ReceivedData)
}
return 1
}
deal(ReceivedData){
global QA,Q_id,SendText
GuiControlGet, show
if RegExMatch(ReceivedData,"(.*)_a(A|B|C|D)",m)
{
if (m2=QA[Q_id]["Answer"])
{
SendText := "正确答案:" m2 ",恭喜" m1 "回答正确!即将换题"
GuiControl, , show, % show ? show "n" SendText : SendText
n" SendText : SendText
gosub, sendall
Sleep, 2000
gosub, change
}
else
{
SendText := m1 "回答错误!"
GuiControl, , show, % show ? show "
gosub, sendall
}
}
}
SendData(WS2_Socket, StringToSend) {
WSA_send(WS2_Socket, &StringToSend, StrLen(StringToSend))
}
WSA_send(__WSA_Socket, __WSA_Data, __WSA_DataLen)
{
Result := DllCall("Ws2_32\send"
, "UInt", __WSA_Socket
, "UInt", __WSA_Data
, "Int", __WSA_DataLen
, "Int", 0)
Return Result
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize%
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
CloseSocket(Socket)
{
Result := DllCall("Ws2_32\closesocket"
, "UInt", Socket)
Return result
}
GuiClose:
exit:
;清除连接
Loop %i% {
CloseSocket(conectioncheck%A_Index%)
}
DllCall("Ws2_32\WSACleanup")
ExitApp
客户端
#singleinstance Off OnExit, exit ;创建窗口以接收数据 Gui, add, Edit, x0 y0 w400 h200 vshow Gui, add, button, x0 y200 w100 h20 gaA, A Gui, add, button, x100 y200 w100 h20 gaB, B Gui, add, button, x200 y200 w100 h20 gaC, C Gui, add, button, x300 y200 w100 h20 gaD, D Gui, show, , 答题游戏客户端 ;客户端名称 服务器地址 端口 ClientName=%A_Computername% ;Network_Address = 218.31.127.210 Network_Address = 127.0.0.1 Network_Port = 1000 ;连接到服务器 socket := ConnectToAddress(Network_Address, Network_Port) if socket = -1 ExitApp ;获取窗口句柄 ;获取窗口句柄 otificationMsg := 0x5555,FD_Read := 1,FD_CLOSE := 32,FD_CONNECT := 20 ;消息号 大于0x1000;当消息可以读取时接收;当连接关闭后时接收 ;设置接收消息的函数 OnMessage(NotificationMsg, "ReceiveData") ;设置接收关联 if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", A_ScriptHwnd, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT) { MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") ExitApp } ;发送连接好消息 ;SendData(socket,ClientName " Login!") return aA: aB: aC: aD: SendData(socket, ClientName "_" A_ThisLabel) return ;连接服务器函数 ConnectToAddress(IPAddress, Port) { VarSetCapacity(wsaData, 32) result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) if ErrorLevel { MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required. return -1 } if result { MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") return -1 }
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
if socket = -1
{
MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
return -1
}
SizeOfSocketAddress = 16
VarSetCapacity(SocketAddress, SizeOfSocketAddress)
InsertInteger(2, SocketAddress, 0, AF_INET)
InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)
if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
{
MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
return -1
}
return socket
}
;接收函数
ReceiveData(wParam, lParam)
{
Critical
global ShowRecieved
socket := wParam
ReceivedDataSize = 4096
Loop
{
VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
if ReceivedDataLength = 0
ExitApp
if ReceivedDataLength = -1
{
WinsockError := DllCall("Ws2_32\WSAGetLastError")
if WinsockError = 10035
return 1
if WinsockError <> 10054
MsgBox % "recv() indicated Winsock error " . WinsockError
ExitApp
}
if ReceivedData
deal(ReceivedData)
}
return 1
}
deal(ReceivedData){
if ReceivedData = Clean
GuiControl, , show,
else
{
GuiControlGet, show
GuiControl, , show, % show ? show "`n" ReceivedData : ReceivedData
}
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize%
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
CloseSocket(Socket)
{
Result := DllCall("Ws2_32\closesocket"
, "UInt", Socket)
Return result
}
SendData(WS2_Socket, StringToSend) {
WSA_send(WS2_Socket, &StringToSend, StrLen(StringToSend))
}
WSA_send(__WSA_Socket, __WSA_Data, __WSA_DataLen)
{
Result := DllCall("Ws2_32\send"
, "UInt", __WSA_Socket
, "UInt", __WSA_Data
, "Int", __WSA_DataLen
, "Int", 0)
Return Result
}
GuiClose:
exit:
;清除连接
if socket
CloseSocket(socket)
DllCall("Ws2_32\WSACleanup")
ExitApp