一个极其简单的AutoIt聊天程序脚本
BY doucment[color=#800080]http://autoit.8800.org/ShowPost.asp?id=174[/color]
说真的,这个程序没有做完,主要是在协议方面,做到后面觉得太复杂,就没得耐心了。发出来的目的是想告诉大家,AutoIt的主流发展我觉得应该是程序语言,最好不要老去用它做一些“按键精灵”可以做到的事情。
刚使用了新的Beta版,我很高兴,因为我终于用它实现了access的存取,解决了数据库的问题。利用它官方网站上的APIFileReadWrite.au3,我正在做一些文件格式分析。autoit最大的好处,我觉得是它能让我这样半路出家的菜鸟从语法繁琐的“大”的程序语言中解脱出来,专注一些算法和分析上的事情。
关于这个脚本,我已经在Internet上测试过,没有问题。如果你想在真正的网络上测试,记得改改$wAddress变量的值。密码是没有用的,直接确定就可以。
希望能够抛砖引玉,有高手把自己的脚本贴出来。^_^
[color=red]Client.au3[/color][code]#include <GUIConstants.au3>
#include "WsaCodes.au3"
HotKeySet("{ESC}", "Terminate")
Dim $SockClient = -1 ; Client socket
Dim $Gui, $GuiConnect
Dim $txtAddress, $txtPort, $cmdConnect, $cmdCancel
Dim $wInput
Dim $txtName,$txtPass
Const $AppTitle = "客户端"
Const $wAddress = "127.0.0.1" ;地址端口
Const $wPort = 9747
$Gui = GuiCreate(" 聊天客户端", 571, 364,(@DesktopWidth-571)/2, (@DesktopHeight-364)/2 , $WS_CAPTION + $WS_SYSMENU + $WS_MINIMIZEBOX)
$mnuConnection = GUICtrlCreateMenu ("连接")
$mnuConnect = GUICtrlCreateMenuitem ("连接",$mnuConnection)
$mnuDisconnect = GUICtrlCreateMenuitem ("断开",$mnuConnection)
$mnuExit = GUICtrlCreateMenuitem ("退出",$mnuConnection)
$viewOutput = GuiCtrlCreateEdit("", 10, 10, 550, 280, $ES_READONLY+$WS_VSCROLL + $WS_HSCROLL + $ES_AUTOVSCROLL + $ES_AUTOHSCROLL)
$txtInput = GuiCtrlCreateInput("", 10, 300, 410, 30)
$cmdSend = GuiCtrlCreateButton("发送", 440, 300, 70, 30, $BS_DEFPUSHBUTTON )
GuiSetState()
Connect()
UpdateForm()
; GUI Message Loop
;==============================================================================================
While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Then ExitLoop ; GUI Closed
If $msg = $mnuExit Then ExitLoop
If $msg = $cmdSend Then
$a=_DoSend(GuiCtrlRead($txtInput))
If $a<>1 Then
MSgbox(0,"错误","发送失败")
ExitLoop
EndIf
EndIf
If $msg = $mnuDisconnect Then _DoDisconnect()
$strBuffer = TCPRecv($SockClient, 512)
If StringLen($strBuffer) <> 0 Then
If $strBuffer = "~~bye" & @CRLF Then
_DoDisconnect()
UpdateView("服务器已经断开连接.")
UpdateForm()
Else; 接受服务器返回信息.
UpdateView($strBuffer);在输出窗口显示数据
UpdateForm()
If @error Then
; The read on the socket has failed with an error
MsgBox(48,"", "从服务器读取数据错误 (Error " & @error & ")")
Return
EndIf
EndIf
EndIf
WEnd
Exit
;==============================================================================================
Func _DoDisconnect()
If $SockClient <> -1 Then
TCPSend($SockClient, "~~bye" & @CRLF)
TCPCloseSocket($SockClient)
$SockClient = -1
EndIf
UpdateForm()
EndFunc
;==============================================================================================
Func _DoSend($SendMessage)
Dim $strBuffer
Dim $nBytesWritten
$strBuffer = _DealMessage($SendMessage) & @CRLF;要发送的信息预处理
GUICtrlSetState($cmdSend, $GUI_DISABLE)
$nBytesWritten = 0
;
GUICtrlSetData($txtInput,"")
; 把数据写入Scoket
$nBytesWritten = TCPSend($SockClient, $strBuffer)
If $nBytesWritten = 0 or @error Then
MsgBox(48,"!", "在发送消息的时候发生错误!. Error " & @error)
Return 0
Else
Return 1
EndIf
EndFunc
;==============================================================================================
;==============================================================================================
Func OnAutoItStart()
TCPStartUp() ; 开始 TCP Services
EndFunc
;==============================================================================================
Func OnAutoItExit()
_DoDisconnect()
TCPCloseSocket($SockClient)
TCPShutDown()
GUIDelete($Gui)
EndFunc
;==============================================================================================
Func _DealMessage($DealMessage)
$DealMessage = StringStripWS($DealMessage,8);去掉空格
$DealMessage = StringReplace($DealMessage, "|", "-");防止与分隔符号混淆
Return $DealMessage
EndFunc
;==============================================================================================
Func UpdateForm();恢复可以输入状态
Dim $strTitle, $bEnable
$strTitle = $AppTitle
If $SockClient <> -1 Then
$strTitle = $txtName & " - " & $AppTitle
GUICtrlSetState($mnuConnect, $GUI_DISABLE)
GUICtrlSetState($mnuDisconnect, $GUI_ENABLE)
GUICtrlSetState($txtInput, $GUI_ENABLE)
GUICtrlSetState($cmdSend, $GUI_ENABLE)
GUICtrlSetState($txtInput, $GUI_FOCUS)
Else
$strTitle = $AppTitle
GUICtrlSetState($mnuConnect, $GUI_ENABLE)
GUICtrlSetState($mnuDisconnect, $GUI_DISABLE)
GUICtrlSetState($txtInput, $GUI_DISABLE)
GUICtrlSetState($cmdSend, $GUI_DISABLE)
EndIf
WinSetTitle($Gui,"", $strTitle)
EndFunc
;==============================================================================================
Func UpdateView($Str);更新显示数据
Dim $Str
$Str=StringReplace($Str,@CRLF,"")
GUICtrlSetData($viewOutput, @Hour&":"&@Min&" "&$Str&@CRLF , 1)
EndFunc
;==============================================================================================
Func Connect()
$GuiConnect = GuiCreate("欢迎使用自编聊天软件客户端", 414, 101,(@DesktopWidth-414)/2, (@DesktopHeight-101)/2 , $WS_CAPTION)
$Label_1 = GuiCtrlCreateLabel("昵称:", 10, 10, 50, 20)
$hwdName = GuiCtrlCreateInput("文档", 70, 10, 320, 30)
$Label_3 = GuiCtrlCreateLabel("密码:", 10, 50, 40, 20)
$hwdPass = GuiCtrlCreateInput("65432", 70, 50, 80, 30,$ES_PASSWORD)
$cmdConnect = GuiCtrlCreateButton("连接", 160, 50, 110, 30)
$cmdCancel = GuiCtrlCreateButton("取消", 280, 50, 110, 30)
GUISwitch($GuiConnect)
GuiSetState()
;UpdateConnectForm()
While 1
$msg = GuiGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
ExitLoop
Case $msg = $cmdCancel
ExitLoop
Case $msg = $cmdConnect
$txtname = GuiCtrlRead($hwdName)
$txtPass=GuiCtrlRead($hwdPass)
_DoConnect()
ExitLoop
EndSelect
WEnd
GUISetState(@SW_HIDE)
GUIDelete($GuiConnect)
GUISwitch($Gui)
Return
EndFunc
;==============================================================================================
Func _DoConnect()
Dim $strError
GUICtrlSetState($cmdConnect, $GUI_DISABLE)
GUISetCursor(15)
$SockClient = TCPConnect($wAddress, $wPort)
If $SockClient = -1 Then
Select
Case @error = $WSAEINTR
;
; This error is generated if the user has pressed the Cancel
; button and canceled the connection attempt; disconnect (close)
; the socket to release any resources allocated for it, and
; unload the form
;
Case @error = $WSAECONNREFUSED
;
; The remote host has refused the connection; this typically
; means that there is no service listening on the specified
; port on that system
;
$strError = "The remote host does not have an active service on the specified port"
Case @error = $WSAETIMEDOUT
;
; The client has timed-out attempting to connect to the
; specified address and port number
;
$strError = "Unable to establish a connection with the remote host"
Case @error = $WSAHOST_NOT_FOUND
;
; The client was unable to resolve the specified hostname into
; an IP address; this typically indicates an invalid hostnane,
; or the inability to query a nameserver (ie: the client is
; using a dial-up networking connection and is offline)
;
$strError = "The server name is invalid, or could not be resolved" & @CRLF
$strError = $strError & "Please check the server name and try again"
Case Else
;
; An unexpected error has occurred
;
$strError = "An unexpected error has occurred (Error " & @error & ")"
EndSelect
GUISetCursor(2)
MsgBox(48,"",$strError)
Return 0
EndIf
TCPSend($SockClient, "~~hello|" &$txtName & "|" &$txtPass) ; send id info
If @error Then
MsgBox(48,"警告!","服务器初始连接错误")
_DoDisconnect()
GUISetCursor(2)
Return
EndIf
GUISetCursor(2)
Return 1
EndFunc
;==============================================================================================
Func UpdateConnectForm()
Dim $bEnable
$bEnable = $GUI_ENABLE
; get data from ui
If StringLen($txtName) = 0 Then
$bEnable = $GUI_DISABLE
Msgbox(0,"警告!","请输入用户昵称")
EndIf
If StringLen($txtPass) = 0 Then
$bEnable = $GUI_DISABLE
Msgbox(0,"警告!","请不要使用空密码!")
GUICtrlSetState($cmdConnect, $bEnable)
EndIf
EndFunc
;==============================================================================================
Func Terminate()
exit
EndFunc [/code]
Server.au3
[code]; AutoIt 聊天服务端; ----------------------
; 描叙: 支持多人聊天及客户端IP显示
; 作者: 文档
; 日期: 2005-06-10
; 环境: AutoIt beta version 3.1.1.45 or higher (TCP support!!)
;
#include
HotKeySet("{ESC}", "Terminate")
Const $g_nMaxClients = 10 ; 最大连接数
Const $wAddress = "127.0.0.1"
Const $wPort = 9747
Dim $g_nLastClient = 0 ; 最后连接的客户
Dim $g_nActiveClients = 0 ; 在线人数
Dim $SockServer[1] ; 服务端 Socket 数组
Dim $Listening = False ; socket 初始化状态
Dim $ClientName[1]
Dim $ClientPass[1]
$SockServer[0] = -1
; Create gui
Dim $Gui
Dim $ServerChat
$Gui = GuiCreate("服务端", 585, 380,(@DesktopWidth-585)/2, _
(@DesktopHeight-380)/2 , $WS_CAPTION + $WS_SYSMENU + $WS_MINIMIZEBOX)
$Label_1 = GuiCtrlCreateLabel("地址:"&$wAddress, 10, 20, 160, 20)
$Label_3 = GuiCtrlCreateLabel("端口:"&$wPort, 100, 20, 130, 20)
$Label_5 = GuiCtrlCreateLabel("最大连接数:"&$g_nMaxClients&"客户", 180, 20, 120, 20)
$viewOutput = GuiCtrlCreateEdit("", 10, 50, 560, 260, $WS_VSCROLL + $WS_HSCROLL + $ES_AUTOVSCROLL + $ES_AUTOHSCROLL)
$cmdListen = GuiCtrlCreateButton("侦听", 390, 10, 70, 25,$BS_DEFPUSHBUTTON )
$CmdDisconnect = GuiCtrlCreateButton("断开", 480, 10, 70, 25,$BS_DEFPUSHBUTTON )
$txtInput = GuiCtrlCreateInput("", 10, 330, 430, 30)
$cmdSend=GuiCtrlCreateButton("发送", 480, 330, 70, 30,$BS_DEFPUSHBUTTON )
GuiSetState()
UpdateForm()
; GUI Message Loop
;=================================================================================
While 1
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Then ExitLoop ; GUI Closed
If $msg = $cmdListen Then ; 用户开始侦听
_DoListen()
EndIf
If $msg = $CmdDisconnect Then ; 断开所有连接
_DoDisconnect()
EndIf
If $msg=$CmdSend Then ;服务端直接发送消息
$ServerChat="服务器公告:"&GuiCtrlRead($txtInput)
_DoEchoAll($ServerChat)
GuiCtrlSetData($txtInput,"")
EndIf
_DoAccept() ; 在正在侦听的Socket上找寻连接客户
_DoEcho() ; 接受客户端连接请求并且发送回信息
;Sleep(250)
WEnd
Exit
;==================================================================================
Func _DoListen() ;启动服务器并且进入侦听模式
Dim $nValue
Dim $nError
If $SockServer[0] <> -1 Then
TCPCloseSocket($SockServer[0])
$SockServer[0] = -1
If @error Then
MsgBox(0,"", "不能断开以前的连接. Error " & @Error)
EndIf
UpdateForm()
Return
EndIf
; 32767以上的端口号转化为负值,以避免溢出
$SockServer[0] = TCPListen($wAddress, $wPort, 100 )
If $SockServer[0] = -1 Then
Select
Case @error = 24048 ;WSAEADDRINUSE
MsgBox(48,"","该端口已经被别的程序占用")
Case Else
MsgBox(48,"","发生未知错误(Error " & @error & ")")
EndSelect
EndIf
UpdateForm()
EndFunc
;=================================================================================
Func _DoDisconnect($ShutDown = False)
Dim $nClient
If Not $ShutDown Then
If MsgBox(36,"警告!","你确定断开所有用户?") = 7 Then
Return
EndIf
EndIf
For $nClient = 1 To $g_nLastClient
If $SockServer[$nClient] <> -1 Then
TCPSend($SockServer[$nClient], "~~bye" & @CRLF)
TCPCloseSocket($SockServer[$nClient])
$SockServer[$nClient] = -1
If Not $ShutDown Then
If @Error Then
MsgBox(48,"", "不能断开用户! " & $nClient & ". Error " & @error)
EndIf
EndIf
$g_nActiveClients = $g_nActiveClients - 1
EndIf
Next
UpdateForm()
EndFunc
;=================================================================================
Func _DoAccept()
Dim $nClient
Dim $strHelo
local $thisSck
Local $thisServerMessage
$thisSck = TCPAccept($SockServer[0])
If $thisSck < 0 Then Return ; 没有请求就返回
; 检查活动连接已经等于最大连接数就拒绝连接
If $g_nActiveClients >= $g_nMaxClients Then
UpdateView("连接太多. 新连接已经被拒绝")
TCPCloseSocket($thisSck)
Return
EndIf
;寻找是否有已经退出的客户端可以启用
For $nClient = 1 To $g_nLastClient
If $SockServer[$nClient] = -1 Then
$SockServer[$nClient] = $thisSck
$strHelo = GetHelo($thisSck,$nClient)
If $strHelo = "right" Then
$thisServerMessage="服务器公告:"&$ClientName[$nClient] &"已登录" & "."&" IP地址为:"&SOCKET2IP($wSck)
_DoEchoAll($thisServerMessage)
$g_nActiveClients = $g_nActiveClients + 1
EndIf
Return
EndIf
Next
;没有找到空位,增加数组
$g_nLastClient = $g_nLastClient + 1
ReDim $SockServer[$g_nLastClient + 1]
ReDim $ClientName[$g_nLastClient + 1]
ReDim $ClientPass[$g_nLastClient + 1]
$SockServer[$g_nLastClient] = $thisSck
$strHelo = GetHelo($thisSck,$nClient)
If $strHelo = "right" then
$thisServerMessage="服务器公告:"&$ClientName[$nClient] &"已登录" & "."&" IP地址为:"&SOCKET2IP($thisSck)
_DoEchoAll($thisServerMessage)
$g_nActiveClients = $g_nActiveClients + 1
EndIf
UpdateForm()
Return
EndFunc
;=================================================================================
Func GetHelo($thisSck,$thisId);服务器校验用户名
Local $buf, $a, $tI
$buf = ""
$tI = TimerInit()
$buf = TCPRecv($thisSck, 512)
If StringLen($buf) > 0 Then
$a = StringSplit($buf, "|")
$ClientName[$thisId]=$a[2]
$ClientPass[$thisId]=$a[3]
Return "right"
Else
Return "error"
EndIf
EndFunc
;=================================================================================
Func _DoEcho() ;
Dim $nClient
Dim $Buffer
Dim $BytesWritten
Local $thisServerMessage
For $nClient = 1 To $g_nLastClient
If $SockServer[$nClient] > 0 Then
$Buffer = TCPRecv($SockServer[$nClient], 512)
If $Buffer <> "" Then
If $Buffer = "~~bye" & @CRLF Then ;客户端断开连接
TCPCloseSocket($SockServer[$nClient])
$SockServer[$nClient] = -1
$g_nActiveClients = $g_nActiveClients - 1
$thisServerMessage="服务器公告:"&$ClientName[$nClient] &"已退出"
_DoEchoAll($thisServerMessage)
UpdateForm()
Else
$thisServerMessage= $ClientName[$nClient] & ": " & $Buffer
_DoEchoAll($thisServerMessage)
EndIf
Else
;TCPSend($SockServer[$nClient], "")
EndIf
EndIf
Next
EndFunc
;=================================================================================
Func _DoEchoAll($sendServerMessage);依次向所有客户端发送消息
Local $thisNClient
For $thisNClient = 1 To $g_nLastClient
If $SockServer[$thisNClient] > 0 Then
$BytesWritten = TCPSend($SockServer[$thisNClient], $sendServerMessage)
UpdateView($sendServerMessage)
If $BytesWritten = 0 Then
; MsgBox(48,"", "向客户端发送消息时发生错误 " & $nClient & ". Error " & @error)
UpdateView("向"&$ClientName[$thisNClient]&"客户端发送消息时发生错误 " & $nClient & ". Error " & @error)
TCPCloseSocket($SockServer[$thisNClient])
$SockServer[$thisNClient] = -1
$g_nActiveClients = $g_nActiveClients - 1
UpdateForm()
EndIF
EndIf
Next
EndFunc
;=================================================================================
Func OnAutoItStart()
TCPStartUp() ; Start The TCP Services
EndFunc
;=================================================================================
Func OnAutoItExit()
_DoDisconnect(True)
TCPCloseSocket($SockServer[0])
TCPShutDown()
GUIDelete($Gui)
EndFunc
;=================================================================================
Func UpdateForm() ;更新主窗口
Dim $strTitle, $bEnable
Const $AppTitle = "服务端"
$strTitle = $AppTitle
$bEnable = $GUI_ENABLE
If $SockServer[0] <> -1 Then
GUICtrlSetData($cmdListen, "暂停")
GUICtrlSetState($cmdListen, $GUI_ENABLE)
Else
$strTitle = $strTitle & " [暂停]"
GUICtrlSetData($cmdListen, "侦听")
GUICtrlSetState($cmdListen, $bEnable)
EndIf
If $g_nActiveClients > 0 Then
GUICtrlSetState($CmdDisconnect, $GUI_ENABLE)
Else
GUICtrlSetState($CmdDisconnect, $GUI_DISABLE)
EndIf
$strTitle = $strTitle & " [" & $g_nActiveClients & " 客户]"
WinSetTitle($Gui,"", $strTitle)
EndFunc
;=================================================================================
Func _GuiGetData() ;数据发送前的处理
EndFunc
;=================================================================================
Func UpdateView($Str)
Dim $Str
GUICtrlSetData($viewOutput, @Hour&":"&@Min&":"&@sec&" "&$Str & @CRLF, 1)
EndFunc
;=================================================================================
Func SOCKET2IP($SHOCKET);寻找连接的IP地址
$sockaddr = DLLStructCreate("short;ushort;uint;char[8]")
$a = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET,"ptr",DLLStructGetPtr($sockaddr),_
"int_ptr",DLLStructGetSize($sockaddr))
If Not @error And $a[0] = 0 Then
$a = DLLCall("Ws2_32.dll","str","inet_ntoa","int",DLLStructGetData($sockaddr,3))
If Not @error Then $a = $a[0]
Else
$a = 0
EndIf
DLLStructDelete($sockaddr)
Return $a
EndFunc
;=================================================================================
Func Terminate()
exit
EndFunc[/code]
WsaCodes.au3
[code]#include-once;
; Windows API $WSAGetLasterror return codes
;
Global Const $WSABASEERR = 24000
Global Const $WSAEINTR = 24004
Global Const $WSAEBADF = 24009
Global Const $WSAEACCES = 24013
Global Const $WSAEFAULT = 24014
Global Const $WSAEINVAL = 24022
Global Const $WSAEMFILE = 24024
Global Const $WSAEWOULDBLOCK = 24035
Global Const $WSAEINPROGRESS = 24036
Global Const $WSAEALREADY = 24037
Global Const $WSAENOTSOCK = 24038
Global Const $WSAEDESTADDRREQ = 24039
Global Const $WSAEMSGSIZE = 24040
Global Const $WSAEPROTOTYPE = 24041
Global Const $WSAENOPROTOOPT = 24042
Global Const $WSAEPROTONOSUPPORT = 24043
Global Const $WSAESOCKTNOSUPPORT = 24044
Global Const $WSAEOPNOTSUPP = 24045
Global Const $WSAEPFNOSUPPORT = 24046
Global Const $WSAEAFNOSUPPORT = 24047
Global Const $WSAEADDRINUSE = 24048
Global Const $WSAEADDRNOTAVAIL = 24049
Global Const $WSAENETDOWN = 24050
Global Const $WSAENETUNREACH = 24051
Global Const $WSAENETRESET = 24052
Global Const $WSAECONNABORTED = 24053
Global Const $WSAECONNRESET = 24054
Global Const $WSAENOBUFS = 24055
Global Const $WSAEISCONN = 24056
Global Const $WSAENOTCONN = 24057
Global Const $WSAESHUTDOWN = 24058
Global Const $WSAETOOMANYREFS = 24059
Global Const $WSAETIMEDOUT = 24060
Global Const $WSAECONNREFUSED = 24061
Global Const $WSAELOOP = 24062
Global Const $WSAENAMETOOLONG = 24063
Global Const $WSAEHOSTDOWN = 24064
Global Const $WSAEHOSTUNREACH = 24065
Global Const $WSAENOTEMPTY = 24066
Global Const $WSAEPROCLIM = 24067
Global Const $WSAEUSERS = 24068
Global Const $WSAEDQUOT = 24069
Global Const $WSAESTALE = 24070
Global Const $WSAEREMOTE = 24071
Global Const $WSASYSNOTREADY = 24091
Global Const $WSAVERNOTSUPPORTED = 24092
Global Const $WSANOTINITIALISED = 24093
Global Const $WSAHOST_NOT_FOUND = 25001
Global Const $WSATRY_AGAIN = 25002
Global Const $WSANO_RECOVERY = 25003
Global Const $WSANO_DATA = 25004
Global Const $WSANO_ADDRESS = 25004[/code]
页:
[1]