明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

機(jī)考系統(tǒng)中的交/發(fā)卷設(shè)計

[摘要]作者: 楊家成 大多數(shù)計算機(jī)考試需要進(jìn)行機(jī)試(如計算機(jī)等級考試),在機(jī)試中會碰到如何給考生分發(fā)試卷及回收答卷等問題。一般的解決方案是: 采用軟盤;在服務(wù)器上建立考生文件夾,設(shè)置登錄密碼或進(jìn)行登錄...
作者: 楊家成

  大多數(shù)計算機(jī)考試需要進(jìn)行機(jī)試(如計算機(jī)等級考試),在機(jī)試中會碰到如何給考生分發(fā)試卷及回收答卷等問題。一般的解決方案是: 采用軟盤;在服務(wù)器上建立考生文件夾,設(shè)置登錄密碼或進(jìn)行登錄限制;基于文件夾共享,以文件復(fù)制方式實現(xiàn)發(fā)卷、交卷。這些方案在實施過程中都存在不少問題,如軟盤的意外損壞; 工作量太大,操作太煩瑣; 共享出來的交卷文件夾可能被考生識破而導(dǎo)致安全隱患等等。相比而言, 采用基于Winsock的文件傳輸方式進(jìn)行發(fā)卷、交卷可以在一定程度上解決這個問題。實踐證明,這是一個行之有效的方案,本文針對這一方案進(jìn)行介紹。

編程思路

本系統(tǒng)的基本思路是: 在局域網(wǎng)環(huán)境下,考試前把各卷別的考試文件分別壓縮,放在服務(wù)器的某個文件夾中,服務(wù)器端執(zhí)行服務(wù)器程序,負(fù)責(zé)接收考生的請求并做出響應(yīng)。各考生執(zhí)行客戶端程序,先通過其中的發(fā)卷模塊向服務(wù)器請求把考試文件發(fā)送到考生的本地硬盤,考試完成后再通過其中的交卷模塊把答案發(fā)送回服務(wù)器。由于文件的發(fā)送是基于TCP協(xié)議的端口通信,考生無從知道試題及答案放在哪里,很好地解決了安全問題。下面是本系統(tǒng)實現(xiàn)過程中的一些關(guān)鍵問題:

1. 多連接的實現(xiàn)

由于有多個考生參加考試,每個考生都要與服務(wù)器建立一個連接,為此在服務(wù)器程序中采用動態(tài)建立多連接,即采用Winsock控件數(shù)組。

2.?dāng)?shù)據(jù)類型

發(fā)送的數(shù)據(jù)類型通常有字串流(String)和字節(jié)流(Char數(shù)組)兩種。前者一般用于發(fā)送輔助信息,如文件大小、考生信息等,后者用于發(fā)送文件正文。

3. 發(fā)送、接收結(jié)束的判斷

每進(jìn)行一次發(fā)送(或接收)后,將已發(fā)送(或已接收)的字節(jié)數(shù)與源文件的大小進(jìn)行比較,判定是否結(jié)束。

4.文件夾的發(fā)送

Winsock控件只能發(fā)送文件,但考試中常常包含文件夾。怎么辦?辦法是先在程序中調(diào)用壓縮軟件將其壓縮成單個文件再發(fā)送,接收方在接收完后進(jìn)行解壓縮還原。這是本系統(tǒng)的一個關(guān)鍵思路。

5.等待壓縮/解壓縮的完成

由于壓縮/解壓縮程序是通過VB的Shell函數(shù)調(diào)用執(zhí)行的,而Shell是以異步方式執(zhí)行壓縮/解壓縮程序的,這樣就會出現(xiàn)沒等壓縮/解壓縮完成,VB代碼繼續(xù)往下執(zhí)行的情況。為此需要借助OpenProcess、GetExitCodeProcess這兩個Windows API,通過循環(huán)讀取進(jìn)程狀態(tài)值控制程序的等待。

6.注意事項

發(fā)送方在發(fā)送數(shù)據(jù)時采用間歇方式,否則易造成客戶端數(shù)據(jù)丟失,通常的做法是執(zhí)行VB的DoEvents語句。接收方在接收期間不能出現(xiàn)與用戶進(jìn)行交互的等待狀態(tài),否則會耽誤接收,造成數(shù)據(jù)丟失。

服務(wù)器端接收考生交卷時,應(yīng)接收完所有考生的壓縮文件后,再統(tǒng)一進(jìn)行解壓縮,否則會加重服務(wù)器的負(fù)擔(dān)。

7. 程序流程

客戶端程序、服務(wù)器程序的流程圖分別如圖1、圖2所示:



關(guān)鍵代碼

1.建立保存考生信息的數(shù)據(jù)類型

先在服務(wù)器程序的標(biāo)準(zhǔn)模塊中創(chuàng)建一個用于存放每個連接有關(guān)信息(每個連接對應(yīng)一個考生)的自定義數(shù)據(jù)類型ClientConn:

Public Type ClientConn

Recvd As Boolean ’是否已接收過數(shù)據(jù)

FileNum As Integer ’文件號

FinishSize As Double ’完成收發(fā)的字節(jié)數(shù)

FileSize As Double ’文件的大小

Gh As String * 6 ’交卷者的考號

Jb As String * 1 ’交卷者的卷別

End Type

在服務(wù)器程序窗體模塊中聲明一個用于記錄所有連接信息的模塊級動態(tài)數(shù)組Conns:

Dim Conns() As ClientConn

2.服務(wù)器端建立連接:

Private Sub wisServer_ConnectionRequest(Index As Integer, ByVal requestID As Long)

If Index = 0 Then

Conncount = Conncount + 1

’連接總數(shù),為模塊級變量

Load wisServer(Conncount)

’服務(wù)器端WinSock控件數(shù)組

ReDim Preserve Conns(1 To Conncount)

wisServer(Conncount).LocalPort = 0

wisServer(Conncount).Accept requestID

End If

End Sub

3.發(fā)卷時服務(wù)器發(fā)送文件正文

Private Sub wisServer_SendComplete(Index As Integer)

Dim DataSize As Integer

Dim outFileData() As Byte

If Conns(Index).FinishSize < Conns(Index).FileSize Then ’此前文件已打開

DoEvents

If Conns(Index).FileSize - Loc(Conns(Index).FileNum) < MAXSENDSIZE Then

’MAXSENDSIZE是每次發(fā)送的最大字節(jié)數(shù)

DataSize = Conns(Index).FileSize - Loc(Conns(Index).FileNum)

Else

DataSize = MAXSENDSIZE

End If

ReDim outFileData(0 To DataSize - 1)

Get #Conns(Index).FileNum, , outFileData

wisServer(Index).SendData outFileData

Conns(Index).FinishSize = Conns(Index).FinishSize + DataSize

Else

Close (Conns(Index).FileNum)

End If

End Sub

說明:客戶端程序的交卷模塊代碼與此類似。

4. 客戶端接收數(shù)據(jù)代碼

Private Sub wisClient_DataArrival(ByVal bytesTotal As Long)

Dim inData As String

’用于接收輔助信息

Dim inFileData() As Byte

’用于接收文件正文

Dim GetRarFile As String, unRarTarget As String ’文件路徑

If Not Recvd Then ’如果是首次接收

wisClient.GetData inData, vbString

’接收文件的大小信息

FileSize = CDbl(Val(inData))

Recvd = True

Else ’開始接收文件正文

ReDim inFileData(0 To bytesTotal - 1)

wisClient.GetData inFileData, vbArray + vbByte

Put FileNum, , inFileData

’此前文件已建立并打開

RecvdSize = RecvdSize + bytesTotal

If RecvdSize = FileSize Then

’接收完畢

Close (FileNum)

wisClient.Close

’由接收方關(guān)閉連接而非發(fā)送方,否則會丟失數(shù)據(jù)

GetRarFile = GhDir & “\” & txtGh & “.rar”

’GhDir是考試目錄,txtGh存放考號

unRarTarget = GhDir & “\”

Pid = Shell(App.path & “\rar x -inul” & GetRarFile & unRarTarget) ’解壓縮

hProcess=OpenProcess(PROCESS_

QUERY_INFORMATION, 0, Pid)

’調(diào)用WinAPI

Do ’等待解壓縮結(jié)束

Call GetExitCodeProcess(hProcess, ExitCode)

DoEvents

Loop While ExitCode = STILL_ALIVE

Call CloseHandle(hProcess)

Kill GhDir & “\” & txtGh & “.rar”

MsgBox “發(fā)卷完畢”

Shell “C:\Windows\explorer.exe/n,

/e,” & GhDir, vbMaximizedFocus

Unload Me

End If

End If

End Sub

說明:服務(wù)器程序中接收交卷的代碼與此相似。

以上代碼已在Windows 2000 Server、Windows XP、Windows 98平臺下成功運行,并在實踐中獲得成功的應(yīng)用。由于篇幅所限,在此沒給出完整代碼。

小 結(jié)

在本系統(tǒng)的編程中有兩點值得注意: 一個是壓縮-發(fā)送-解壓縮的思路,另一個是用自定義數(shù)據(jù)類型數(shù)組保存考生(連接)的信息。當(dāng)然,本系統(tǒng)只是解決了服務(wù)器與考生用機(jī)之間的安全問題,至于考生與考生之間通過文件夾共享互通答案,也許只有采取暫時的物理隔離手段才是最有效的解決辦法。