/*
* 服务器程序只能运行在 Windows NT,
* version 3.51 或更高的版本上.
* 不能运行在 Windows 95 上.
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>
#include <string.h>
#include <winsock.h>
#include <io.h>
#include <ODBCINST.H>
#include <SQLEXT.H>
#include <time.h>
#include <winbase.h>
#include "MtVerify.h"
#pragma comment (lib,"WS2_32.lib"
#pragma comment (lib,"ODBC32.lib"
#define SERV_TCP_PORT 5554
#define MAXLINE 1024
// 用 key 追踪 每一个单独的文件句柄
// 的I/O 端口的状态.
struct ContextKey
{
SOCKET sock;
char InBuffer[4]; // 输入
OVERLAPPED ovIn;
int nOutBufIndex;
char OutBuffer[MAXLINE]; // 输出
OVERLAPPED ovOut;
DWORD dwWritten;
};
struct User
{
char Subject[50];
char Name[50];
char PassWord[50];
};
/*结构体定义*/
//试卷每道题的结构
struct TestRubric{
char Questions[512];
char SelectObject[4][256];
};
//时间结构
//生成的试卷
//
// 全局变量
//
HANDLE ghCompletionPort;
//数据库全局变量
SQLHANDLE hEnv; //ODBC环境句柄
SQLHANDLE hConn; //ODBC连接句柄
SCHAR * strConnect ="DRIVER={Microsoft Access Driver (*.mdb)};DBQ=";
SCHAR * DBName="exam.mdb";
SCHAR ProgPath[256];
char Conn[256]; //ODBC驱动连接返完整字符返回缓冲区
SCHAR ConnectString[1024];
char UserAttrib[50];
//
// 函数申明
//
void CreateWorkerThreads();
DWORD WINAPI ThreadFunc(LPVOID pvoid);
void IssueRead(struct ContextKey *pCntx);
void CheckOsVersion();
void FatalError(char *s);
void SendString(char *p,struct ContextKey *pCntx);
//数据库操作函数
void ODBCConnect(SCHAR *strConnect,SCHAR *ProgPath,SCHAR *DBName); //ODBC数据连接子程序
BOOL LoginSever(char * LpText,struct User *login,char *p); //登陆操作函数
BOOL GetState(struct User US,char *p); //获取试卷状态子函数
int GetNumbers(struct User US,char *P); //获取试卷状态子函数
BOOL initTestPapers(struct User US,int Num,struct TestRubric * TestPapers); //初始化试卷
void GetQuestions(struct TestRubric * TestPapers,char * buffers); //发送缓冲区格式化试题子函数;
BOOL ScanTime(struct User US,char * P,struct ContextKey *pCntx); //设置试卷状态子函数
void ChangeState(struct User US,char State[5]);
void SaveResult(struct User US,char Result[1024]);
BOOL GetResult(struct User US,char *p); //获得试卷做答子函数
void ChangeState2(struct User US,char State[5],char Result[1024]);
///////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
SOCKET listener;
SOCKET newsocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;
printf("-----------------------------------------------------------------------/n"
;
printf("* 考试系统服务端程序 */n"
;
printf("* 服务器程序只能运行在 Windows NT,version 3.51 或更高的版本上. */n"
;
printf("* -------- 2003.12.25 */n"
;
printf("* yaomingmail@sina.com */n"
;
printf("-----------------------------------------------------------------------/n"
;
GetCurrentDirectory(256,ProgPath); //获得程序路径
ProgPath[strlen(ProgPath)]='//';
ODBCConnect(strConnect,ProgPath,DBName); //建立数据库联接
CheckOsVersion();
err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR)
{
FatalError("网络初始化失败."
;
return EXIT_FAILURE;
}
listener = socket(AF_INET, SOCK_STREAM, 0); //开启一个socket 套节字
if (listener < 0)
{
FatalError("socket() 错误-请检查 TCP/IP 是否正确安装?"
;
return EXIT_FAILURE;
}
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(SERV_TCP_PORT);
err = bind(listener, // 绑定我们的局域地址
(struct sockaddr *)&serverAddress,
sizeof(serverAddress));
if (err < 0)
FatalError("bind() 错误-请检查 TCP/IP 是否正确安装?"
;
ghCompletionPort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL,0,0);
if (ghCompletionPort == NULL)
FatalError("CreateIoCompletionPort() 错误-请检查系统是否是Windows NT version 3.51 或更高版本."
;
CreateWorkerThreads(ghCompletionPort);
listen(listener, 5);
fprintf(stderr, "服务器启用 I/O Completion Ports 模式:端口 %d/n", SERV_TCP_PORT);
fprintf(stderr, "/nCtrl+C 停止服务器程序/n"
;
printf("/n-----------------------------------------------------------------------/n"
;
fprintf(stderr, "开始监听客户端:/n"
;
//
// 无限循环,接受并处理新的连接
//
for (;
{
struct ContextKey *pKey;
clientAddressLength = sizeof(clientAddress);
newsocket = accept(listener,
(struct sockaddr *)&clientAddress,
&clientAddressLength);
if (newsocket < 0)
{
FatalError("accept() 错误."
;
return EXIT_FAILURE;
}
/*
*建立一个 key 并初始化它.
*/
pKey = calloc(1, sizeof(struct ContextKey)); // calloc 将使 buffer 区域清零.
pKey->sock = newsocket;
pKey->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//为写信息包过程设置(事件对象) event .
pKey->ovOut.hEvent = (HANDLE)((DWORD)pKey->ovOut.hEvent | 0x1);
CreateIoCompletionPort( //为请求绑定端口
(HANDLE)newsocket,
ghCompletionPort,
(DWORD)pKey,
0
);
IssueRead(pKey); // 完成第一次读操作
}
SQLDisconnect(hConn);
SQLFreeHandle(SQL_HANDLE_DBC,hConn);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return 0;
}
void CreateWorkerThreads()
{
SYSTEM_INFO sysinfo;
DWORD dwThreadId;
DWORD dwThreads;
DWORD i;
GetSystemInfo(&sysinfo);
dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2;
for (i=0; i<dwThreads; i++)
{
HANDLE hThread;
hThread = CreateThread(
NULL, 0, ThreadFunc, NULL, 0, &dwThreadId
);
CloseHandle(hThread);
}
}
//
// 每一个工作线程从这里开始.
//
DWORD WINAPI ThreadFunc(LPVOID pVoid)
{
struct User users;
struct TestRubric * TestPapers;
BOOL bResult;
DWORD dwNumRead;
struct ContextKey *pCntx;
LPOVERLAPPED lpOverlapped;
char Temp[50];
int i,QueNums;
char buffers[1024];
UNREFERENCED_PARAMETER(pVoid);
// 无限循环从 I/O completion port 获取信息.
for (;
{
bResult = GetQueuedCompletionStatus(
ghCompletionPort,
&dwNumRead,
&(DWORD)pCntx,
&lpOverlapped,
INFINITE
);
if (bResult == FALSE
&& lpOverlapped == NULL)
{
FatalError(
"ThreadFunc - GetQueuedCompletionStatus()错误./n"
;
}
else if (bResult == FALSE
&& lpOverlapped != NULL)
{
// This happens occasionally instead of
// end-of-file. Not sure why.
closesocket(pCntx->sock);
free(pCntx);
fprintf(stderr,"用户非正常退出./n"
;
}
else if (dwNumRead == 0)
{
closesocket(pCntx->sock);
free(pCntx);
fprintf(stderr, "用户已经关闭端口./n"
;
fprintf(stderr, "------------------./n"
;
}
else
{
char *pch = &pCntx->OutBuffer[pCntx->nOutBufIndex++];
*pch++ = pCntx->InBuffer[0];
*pch = '/0';
if (pCntx->InBuffer[0] == '/n')
{
for(i=0;i<6;i++)
Temp
=pCntx->OutBuffer;
Temp='/0';
if(!strcmp(Temp,"login:")
{
if(LoginSever(pCntx->OutBuffer,&users,Temp))
SendString(Temp,pCntx);
else
SendString("无法识别的用户.",pCntx);
}
else if(!strcmp(Temp,"Srecv:")
{
for(i=0;i<7;i++)
Temp=pCntx->OutBuffer[i+6];
Temp='/0';
if (!strcmp(Temp,"ScanTm:")
if(ScanTime(users,buffers,pCntx))
fprintf(stderr,"%s %s试卷状态设置成功./n",users.Name,users.Subject);
else
{
fprintf(stderr,"设置 %s 的 %s 试卷状态失败./n",users.Name,users.Subject);
SendString("服务器设置试卷状态失败.",pCntx);
}
else if(!strcmp(Temp,"GetSta:")
{
if(GetState(users,Temp))
SendString(Temp,pCntx);
}
else if(!strcmp(Temp,"GetRlt:")
{
if (GetResult(users,buffers))
SendString(buffers,pCntx);
else SendString("Erro",pCntx);
}
else if(!strcmp(Temp,"GetNum:")
{
if(QueNums=GetNumbers(users,buffers))
{
SendString(buffers,pCntx);
fprintf(stderr,"用户获取 %s 试卷总题数 %d 成功./n",users.Subject,QueNums);
TestPapers=(struct TestRubric *)malloc(sizeof(struct TestRubric)*QueNums);
if(TestPapers==NULL)
fprintf(stderr,"申请动态内存失败."
else if(!initTestPapers(users,QueNums,TestPapers))
{
fprintf(stderr,"初始化试卷失败./n"
free(TestPapers);
}
else fprintf(stderr,"初始化试卷成功./n"
}
else fprintf(stderr,"用户获取 %s 试卷总题数失败./n",users.Subject);
}
else if(!strcmp(Temp,"GetQue:")
{
for(i=0;pCntx->OutBuffer!='/n';i++);
pCntx->OutBuffer='/0';
i=0;
i=atoi(&pCntx->OutBuffer[13]);
GetQuestions(TestPapers+i,buffers);
SendString(buffers,pCntx);
fprintf(stderr,"成功发送 %s : %s 试卷的第 %d 题./n",users.Name,users.Subject,i+1);
}
else if(!strcmp(Temp,"SaveDt:")
{
SaveResult(users,&(pCntx->OutBuffer[13]));
}
else if(!strcmp(Temp,"ChanST:")
ChangeState2(users,"3",&(pCntx->OutBuffer[13]));
}
else if(!strcmp(Temp,"trecv:"){}
else if(!strcmp(Temp,"arecv:"){}
else if(!strcmp(Temp,"ssave:"){}
else if(!strcmp(Temp,"tsave:"){}
else if(!strcmp(Temp,"asave:"){}
pCntx->nOutBufIndex = 0;
fprintf(stderr, " Echo on socket %x./n", pCntx->sock);
}
// 开始读取
IssueRead(pCntx);
}
}
return 0;
}
/*
* 调用 ReadFile 开始一个异步请求
* 重复获取我们的句柄状态
*/
void IssueRead(struct ContextKey *pCntx)
{
int i = 0;
BOOL bResult;
int err;
int numRead;
while (++i)
{
// 读取一个单字符
bResult = ReadFile(
(HANDLE)pCntx->sock,
pCntx->InBuffer,
1,
&numRead,
&pCntx->ovIn
);
// 这里,等待一个信息包.
if (bResult)
return;
err = GetLastError();
// 获取状态,这里并不代表错误
if (err == ERROR_IO_PENDING)
return;
if ( err == ERROR_INVALID_USER_BUFFER ||
err == ERROR_NOT_ENOUGH_QUOTA ||
err == ERROR_NOT_ENOUGH_MEMORY )
{
if (i == 5)
{
Sleep(50); // 等待并重试
continue;
}
FatalError("IssueRead -系统溢出连接池"
}
break;
}
fprintf(stderr, "IssueRead - 读信息失败./n"
}
//
// 确保我们运行在正确的版本下 Windows NT (3.51, 4.0, or later)
//
void CheckOsVersion()
{
OSVERSIONINFO ver;
BOOL bResult;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
if ( (!bResult) ||
(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
{
FatalError("ECHOSRV requires Windows NT 3.51 or later."
}
}
//发送字符串子程序
void SendString(char *p,struct ContextKey *pCntx)
{
int len;
strcpy(pCntx->OutBuffer,p);
len=strlen(pCntx->OutBuffer);
pCntx->OutBuffer[len++]='/n';
pCntx->OutBuffer[len]='/0';
pCntx->nOutBufIndex=strlen(pCntx->OutBuffer);
WriteFile(
(HANDLE)(pCntx->sock),
pCntx->OutBuffer,
pCntx->nOutBufIndex,
&pCntx->dwWritten,
&pCntx->ovOut
);
}
//
// 错误句柄
//
void FatalError(char *s)
{
fprintf(stdout, "%s/n", s);
exit(EXIT_FAILURE);
}
//数据库联接函数
void ODBCConnect(SCHAR *strConnect,SCHAR *ProgPath,SCHAR *DBName)
{
SWORD StrLen; //返回缓冲区长度
SQLRETURN RB; //ODBC函数返回错误校验变量
strcat(ConnectString,strConnect);
strcat(ConnectString,ProgPath);
strcat(ConnectString,DBName);
RB=SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,&hEnv); //获取环境句柄
if (RB==SQL_SUCCESS || RB==SQL_SUCCESS_WITH_INFO)
{
RB=SQLSetEnvAttr(hEnv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0); //设置OBDC启用版本
if (RB==SQL_SUCCESS || RB==SQL_SUCCESS_WITH_INFO)
{
RB=SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hConn); //获取连接句柄
if (RB==SQL_SUCCESS || RB==SQL_SUCCESS_WITH_INFO)
{
RB=SQLDriverConnect(hConn,NULL,(LPSTR)ConnectString,(SQLSMALLINT)strlen(ConnectString),(LPSTR)Conn,(SQLSMALLINT)strlen(Conn),&StrLen,SQL_DRIVER_NOPROMPT); //联接OBDC驱动程序
if (RB==SQL_SUCCESS || RB==SQL_SUCCESS_WITH_INFO)
printf("/n学生考试系统数据库连接成功:/n%s%s/n/n",ProgPath,DBName);
else
{
SQLFreeHandle(SQL_HANDLE_DBC, hConn); //释放句柄
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
FatalError("ODBC驱动程序连接失败!/n"
}
}
else
{
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
FatalError("ODBC连接句柄获取失败!/n"
}
}
else
{
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
FatalError("设置ODBC工作版本失败!/n"
}
}
else
FatalError("ODBC环境句柄获取失败!/n"
}
//登陆操作函数
BOOL LoginSever(char * LpText,struct User *login,char *p)
{
SQLINTEGER PassLength; //返回缓冲区长度
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
char * Temp;
char Attribute[50];
char *SQLStatement="select 用户等级 from 用户管理 where 科目=? and 账号=? and 密码=?";
LpText+=6;
Temp=LpText;
while(*Temp)
{
if(*Temp=='#')
*Temp='/0';
Temp++;
}
strcpy(login->Subject,LpText);
LpText+=(strlen(LpText)+1);
strcpy(login->Name,LpText);
LpText+=(strlen(LpText)+1);
strcpy(login->PassWord,LpText);
fprintf(stderr, "/n*****************************/n"
fprintf(stderr, "用户:%s............请求登陆./n",login->Name);
fprintf(stderr, "科目:%s /n",login->Subject);
fprintf(stderr, "密码/考号:%s/n",login->PassWord);
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,login->Subject,strlen(login->Subject),NULL);
SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,login->Name,strlen(login->Name),NULL);
SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,login->PassWord,strlen(login->PassWord),NULL);
SQLPrepare(hStmt,SQLStatement,strlen(SQLStatement));
RC=SQLExecute(hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,Attribute,strlen(Attribute),&PassLength);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "用户登陆失败./n"
fprintf(stderr, "*****************************/n/n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
fprintf(stderr, "用户登陆成功./n"
fprintf(stderr, "用户属于/"%s/"./n",Attribute);
fprintf(stderr, "*****************************/n/n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
strcpy(p,Attribute);
return 1;
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
}
else
{
fprintf(stderr,"/n语句句柄获取失败/n"
return 0;
}
}
//获取试卷状态子程序
BOOL GetState(struct User US,char *p)
{
char *SQLStatement="select 试卷状态 from 试卷信息表 where 科目名称=?";
char *SQLStatement2="select 试卷状态 from 学生试卷成绩表 where 科目=? and 姓名=? and 考号=?";
SQLINTEGER PassLength; //返回缓冲区长度
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
char State[5];
char State2[5];
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLExecDirect(hStmt,SQLStatement,strlen(SQLStatement));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,State,strlen(State),&PassLength);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "没有用户所要的 %s 试卷./n",US.Subject);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
strcpy(p,"0"
return 1;
}
if(!strcmp(State,"0")
{
fprintf(stderr, "用户所要试卷还未经过审核./n"
strcpy(p,State);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 1;
}
SQLFreeStmt(hStmt,SQL_RESET_PARAMS);
SQLFreeStmt(hStmt,SQL_UNBIND);
SQLFreeStmt(hStmt,SQL_CLOSE);
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement2,strlen(SQLStatement2));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,State2,strlen(State2),&PassLength);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "无此用户的试卷信息./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
strcpy(p,State2);
fprintf(stderr, "用户获取试卷状态成功./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 1;
}
}
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
else
{
fprintf(stderr,"/n语句句柄获取失败/n"
return 0;
}
}
//获取试卷信息子函数
int GetNumbers(struct User US,char *P)
{
char *SQLStatement="select 建考时间,开考时间,结束时间,监考人,题目数量 from 试卷信息表 where 科目名称=?";
int Num=0;
SQLINTEGER sCustID,sCustID1,sCustID2,sCustID3,sCustID4; //返回缓冲区长度
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
DATE_STRUCT Date;
TIMESTAMP_STRUCT Time1,Time2;
char People[20];
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLExecDirect(hStmt,SQLStatement,strlen(SQLStatement));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_DATE,&Date,0,&sCustID);
SQLBindCol(hStmt,2,SQL_C_TIMESTAMP,&Time1,0,&sCustID1);
SQLBindCol(hStmt,3,SQL_C_TIMESTAMP,&Time2,0,&sCustID2);
SQLBindCol(hStmt,4,SQL_C_CHAR,&People,20,&sCustID3);
SQLBindCol(hStmt,5,SQL_C_USHORT,&Num,0,&sCustID4);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "没有用户所要的 %s 试卷./n",US.Subject);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
wsprintf(P,"%d#%d#%d#%d#%d#%d#%d#%d#%d#%d#%s",Date.year,Date.month,Date.day,Time1.hour,Time1.minute,Time1.second,Time2.hour,Time2.minute,Time2.second,Num,People);
return Num;
}
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
fprintf(stderr,"/n语句句柄获取失败/n"
return 0;
}
//格式化试题子函数
void GetQuestions(struct TestRubric * TestPapers,char * buffers)
{
int i,n;
strcpy(buffers,TestPapers->Questions);
n=strlen(buffers);
buffers[n++]='#';
for(i=0;i<4;i++)
{
strcpy(&buffers[n],TestPapers->SelectObject);
n=strlen(buffers);
buffers[n++]='#';
}
buffers[n]='/0';
}
//初始化试卷
BOOL initTestPapers(struct User US,int Num,struct TestRubric * TestPapers)
{
char *SQLStatement="select 考题序列 from 学生试卷成绩表 where 科目=? and 姓名=? and 考号=?";
char *SQLStatement2="select * from 题库表 where 题号=?";
SQLINTEGER PassLength,TestID,TestID2,TestID3,TestID4,TestID5; //返回缓冲区长度
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
char TestPaper[512];
char Temp[28];
int i,j,n,k=0;
SQLINTEGER Test;
struct TestRubric BinTest;
int *THao=malloc(sizeof(int)*Num);
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement,strlen(SQLStatement));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,TestPaper,strlen(TestPaper),&PassLength);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "没有用户所要的 %s 试卷./n",US.Subject);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
n=strlen(TestPaper);
for(i=0;i<n;i++)
{
for (j=0;TestPaper!='#';j++,i++)
Temp[j]=TestPaper;
Temp[j]='/0';
THao[k++]=atoi(Temp);
}
SQLFreeStmt(hStmt,SQL_UNBIND);
SQLFreeStmt(hStmt,SQL_CLOSE);
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,10,0,&Test,0,NULL);
SQLBindCol(hStmt,4,SQL_C_CHAR,BinTest.Questions,strlen(BinTest.Questions),&TestID);
SQLBindCol(hStmt,5,SQL_C_CHAR,BinTest.SelectObject[0],strlen(BinTest.SelectObject[0]),&TestID2);
SQLBindCol(hStmt,6,SQL_C_CHAR,BinTest.SelectObject[1],strlen(BinTest.SelectObject[1]),&TestID3);
SQLBindCol(hStmt,7,SQL_C_CHAR,BinTest.SelectObject[2],strlen(BinTest.SelectObject[2]),&TestID4);
SQLBindCol(hStmt,8,SQL_C_CHAR,BinTest.SelectObject[3],strlen(BinTest.SelectObject[3]),&TestID5);
for(i=0;i<Num;i++)
{
Test=THao;
SQLPrepare(hStmt,SQLStatement2,strlen(SQLStatement2));
RC=SQLExecute(hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "没有找到用户所要 %s 试卷的第 %d 题./n",US.Subject,i);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
free(THao);
return 0;
}
strcpy(TestPapers->Questions,BinTest.Questions);
strcpy(TestPapers->SelectObject[0],BinTest.SelectObject[0]);
strcpy(TestPapers->SelectObject[1],BinTest.SelectObject[1]);
strcpy(TestPapers->SelectObject[2],BinTest.SelectObject[2]);
strcpy(TestPapers->SelectObject[3],BinTest.SelectObject[3]);
TestPapers++;
SQLFreeStmt(hStmt,SQL_CLOSE);
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
free(THao);
fprintf(stderr,"/nSQL语句执行失败/n"
free(THao);
return 0;
}
}
free(THao);
return 1;
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
free(THao);
fprintf(stderr,"获取题目集合失败./n"
return 0;
}
}
else
{
free(THao);
fprintf(stderr,"获取语句句柄失败./n"
return 0;
}
}
BOOL ScanTime(struct User US,char * P,struct ContextKey *pCntx)
{
char *SQLStatement="select 建考时间,开考时间,结束时间 from 试卷信息表 where 科目名称=?";
char *SQLStatement2="select 试卷状态 from 学生试卷成绩表 where 科目=? and 姓名=? and 考号=?";
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
DATE_STRUCT Date;
SQLINTEGER sCustID,sCustID1,sCustID2,PassLength;
TIMESTAMP_STRUCT Time1,Time2;
SYSTEMTIME TM;
char State[5];
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement2,strlen(SQLStatement2));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,State,strlen(State),&PassLength);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "无此用户的试卷信息./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
fprintf(stderr, "用户获取试卷状态成功./n"
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
SQLFreeStmt(hStmt,SQL_RESET_PARAMS);
SQLFreeStmt(hStmt,SQL_UNBIND);
SQLFreeStmt(hStmt,SQL_CLOSE);
SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLExecDirect(hStmt,SQLStatement,strlen(SQLStatement));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_DATE,&Date,0,&sCustID);
SQLBindCol(hStmt,2,SQL_C_TIMESTAMP,&Time1,0,&sCustID1);
SQLBindCol(hStmt,3,SQL_C_TIMESTAMP,&Time2,0,&sCustID2);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "没有用户所要的 %s 试卷./n",US.Subject);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
GetSystemTime(&TM);
TM.wHour+=8;
if(TM.wYear<Date.year||
(TM.wYear==Date.year&&TM.wMonth<Date.month)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay<Date.day)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour<Time1.hour)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour==Time1.hour&&TM.wMinute<Time1.minute)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour==Time1.hour&&TM.wMinute==Time1.minute&&TM.wSecond<Time1.second))
//将试卷状态改为0
{
ChangeState(US,"2"
SendString("服务器设置试卷状态成功.",pCntx);
}
else if(TM.wYear>Date.year||
(TM.wYear==Date.year&&TM.wMonth>Date.month)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay>Date.day)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour>Time2.hour)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour==Time2.hour&&TM.wMinute>Time2.minute)||
(TM.wYear==Date.year&&TM.wMonth==Date.month&&TM.wDay==Date.day&&TM.wHour==Time2.hour&&TM.wMinute==Time2.minute&&TM.wSecond>Time2.second))
//将试卷状态改为3
{
ChangeState(US,"3"
SendString("服务器设置试卷状态成功.",pCntx);
}
else
//将试卷状态改为1
{
if(strcmp(State,"3")
ChangeState(US,"1"
sprintf(P,"%c%u",'t',(Time2.hour-TM.wHour)*60*60+(Time2.minute-TM.wMinute)*60+(Time2.second-TM.wSecond));
SendString(P,pCntx);
}
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 1;
}
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
fprintf(stderr,"/n语句句柄获取失败/n"
return 0;
}
//改变试卷状态子函数
void ChangeState(struct User US,char State[5])
{
char *SQLStatement2="update 学生试卷成绩表 set 试卷状态=? where 科目=? and 姓名=? and 考号=?";
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,5,0,State,strlen(State),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,4,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement2,strlen(SQLStatement2));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
fprintf(stderr, "设置试卷状态成功./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
}
}
else
fprintf(stderr,"/n语句句柄获取失败/n"
}
void SaveResult(struct User US,char Result[1024])
{
char *SQLStatement2="update 学生试卷成绩表 set 答案序列=? where 科目=? and 姓名=? and 考号=?";
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
char *Temp;
int LpText;
Temp=Result;
while(*Temp!='*')
{
if(*Temp=='#')
*Temp='/0';
Temp++;
}
*Temp='/0';
strcpy(US.Name,Result);
LpText=strlen(Result)+1;
strcpy(US.Subject,&Result[LpText]);
LpText+=(strlen(&Result[LpText])+1);
strcpy(US.PassWord,&Result[LpText]);
LpText+=(strlen(&Result[LpText])+1);
Result[LpText+strlen(&Result[LpText])-1]='/0';
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_LONGVARCHAR,1024,0,&Result[LpText],strlen(&Result[LpText]),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,4,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement2,strlen(SQLStatement2));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
fprintf(stderr, "%s 保存%s试卷成功./n",US.Name,US.Subject);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
}
}
else
fprintf(stderr,"/n语句句柄获取失败/n"
}
BOOL GetResult(struct User US,char *p)
{
char *SQLStatement="select 答案序列 from 学生试卷成绩表 where 科目=? and 姓名=? and 考号=?";
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
SQLINTEGER sCustID;
char buffers[1024];
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement,strlen(SQLStatement));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
SQLBindCol(hStmt,1,SQL_C_CHAR,buffers,strlen(buffers),&sCustID);
if(SQLFetch(hStmt)==SQL_NO_DATA)
{
fprintf(stderr, "无此用户的试卷作答信息./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
return 0;
}
if(buffers[0]<'0'||buffers[0]>'4') return 0;
strcpy(p,buffers);
fprintf(stderr, "用户获取试卷作答信息成功./n"
return 1;
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
return 0;
}
}
fprintf(stderr,"/n语句句柄获取失败/n"
return 0;
}
void ChangeState2(struct User US,char State[5],char Result[1024])
{
char *SQLStatement2="update 学生试卷成绩表 set 试卷状态=? where 科目=? and 姓名=? and 考号=?";
SQLHANDLE hStmt; //ODBC语句句柄
SQLRETURN RC; //ODBC函数返回错误校验变量
char *Temp;
int LpText;
Temp=Result;
while(*Temp!='*')
{
if(*Temp=='#')
*Temp='/0';
Temp++;
}
*Temp='/0';
strcpy(US.Name,Result);
LpText=strlen(Result)+1;
strcpy(US.Subject,&Result[LpText]);
LpText+=(strlen(&Result[LpText])+1);
strcpy(US.PassWord,&Result[LpText]);
LpText+=(strlen(&Result[LpText])+1);
Result[LpText+strlen(&Result[LpText])-1]='/0';
RC=SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
RC=SQLBindParameter(hStmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,5,0,State,strlen(State),NULL);
RC=SQLBindParameter(hStmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Subject,strlen(US.Subject),NULL);
RC=SQLBindParameter(hStmt,3,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.Name,strlen(US.Name),NULL);
RC=SQLBindParameter(hStmt,4,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,50,0,US.PassWord,strlen(US.PassWord),NULL);
RC=SQLExecDirect(hStmt,SQLStatement2,strlen(SQLStatement2));
if (RC==SQL_SUCCESS || RC==SQL_SUCCESS_WITH_INFO)
{
fprintf(stderr, "设置试卷状态成功./n"
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
fprintf(stderr,"/nSQL语句执行失败/n"
}
}
else
fprintf(stderr,"/n语句句柄获取失败/n"
}