连接数据库:
MYSQL m_sqlCon;
mysql_init(&m_sqlCon);//初始化数据库对象
if (!mysql_real_connect(&m_sqlCon, "localhost", "root", "123456", "student", 3306, NULL, 0))
//localhost:服务器地址,可以直接填入IP;root:账号;123:密码;test:数据库名;3306:网络端口
{
AfxMessageBox(_T("数据库连接失败!"));
return FALSE;
}
else//连接成功则继续访问数据库,之后的相关操作代码基本是放在这里面的
{
AfxMessageBox(_T("数据库连接成功!"));
}
传输的结构体定义netStruch:
#define LOGIN_MSGID 10003//登录
#define LOGIN_RESULT_MSGID 10008
#define REGISTER_MSGID 10007
#define REGISTER_RESULT_MSGID 10009//注册
#define ALLCOURSE_MSGID 10010 //查询全部课程
#define ALLCOURSE_RESULT_MSGID 10011
#define STUDENT_COURSE_MSGID 10012 //查询全部课程
#define STUDENT_COURSE_RESULT_MSGID 10013
#define STUDENT_ADD_COURSE_MSGID 10014
#define STUDENT_ADD_COURSE_RESULT_MSGID 10015
#define STUDENT_DELETE_COURSE_MSGID 10016
#define STUDENT_DELETE_COURSE_RESULT_MSGID 10017
struct LOGIN{//客户端发送给服务器
short msgID;
char userId[32];
char userPassword[32];
};
struct LOGIN_RESULT {//服务器返回结果给客户端
short msgID;
char result[32];
};
struct REGISTER
{
short msgID;
char userId[32];
char userName[32];
char userPassword[32];
};
struct REGISTER_RESULT {
short msgID;
char result[32];
};
struct ALLCOURSE {
short msgID;
};
struct ALLCOURSE_RESULT {
short msgID;
short row;//显示在第几行
char courseId[32];
char courseName[32];
char courseScore[32];
char courseTime[32];
char coursePeople[32];
char teacherId[32];
};
struct STUDENT_COURSE {
short msgID;
char userId[32];
};
struct STUDENT_ADD_COURSE {
short msgID;
char userId[32];
char courseId[32];
};
struct STUDENT_ADD_COURSE_RESULT {//服务器返回结果给客户端
short msgID;
char result[32];
};
struct STUDENT_DELETE_COURSE {
short msgID;
char userId[32];
char courseId[32];
};
struct STUDENT_DELETE_COURSE_RESULT {//服务器返回结果给客户端
short msgID;
char result[32];
};
服务器中写SOCKET:
SOCKET s[5];
int j = 0;
//剩下的都是有事件发生的套接字
for (int i = 0; i < tmSet.fd_count; i++)
{
if (tmSet.fd_array[i] == lisSock) //如果是监听监听套接字
{
SOCKET cliSock = accept(lisSock, 0, 0);
printf("新连接.\n");
FD_SET(cliSock, &fds); //将已连接的套接字加入数组中
}
else
{
char recvBuf[1024] = { 0 };
int recvLen = recv(tmSet.fd_array[i], recvBuf, 1024, 0);
if (recvLen > 0)
{
//接收到客户端的数据后进行处理
HandleData(recvBuf,recvLen,m_sqlCon, tmSet.fd_array[i]);
}
else //错误发生,或者客户端断开连接
{
printf("客户已断开\n");
FD_CLR(tmSet.fd_array[i], &fds); //从数组中移除已端口的客户端
}
}
}
服务器处理接收到的数据dataHandle.cpp:
//处理收到的数据
bool HandleData(const char* recvData,int len, MYSQL &sqlCon, SOCKET lisSock)
{
short msgID = *(short*)recvData;
switch (msgID)
{
case LOGIN_MSGID://登录消息
{
DB_Login(recvData, len, sqlCon, lisSock);
}
break;
case REGISTER_MSGID://注册消息
{
DB_Register(recvData, len, sqlCon, lisSock);
}
break;
case ALLCOURSE_MSGID://查询全部课程消息
{
DB_AllCourse(recvData, len, sqlCon, lisSock);
}
break;
case STUDENT_COURSE_MSGID://查询全部课程消息
{
DB_Student_Course(recvData, len, sqlCon, lisSock);
}
break;
case STUDENT_ADD_COURSE_MSGID://学生添加课程消息
{
DB_Student_AddCourse(recvData, len, sqlCon, lisSock);
}
break;
case STUDENT_DELETE_COURSE_MSGID://学生删除课程消息
{
DB_Student_DeleteCourse(recvData, len, sqlCon, lisSock);
}
break;
case TALKALL_MSGID:
{
//...给所有人的消息
const MSG_TALKALL* takAll = (MSG_TALKALL*)recvData;
printf("群聊消息: %s\n", takAll->Content);
}
break;
case TALKONE_MSGID:
{
//给某个人的消息
const MSG_TALKONE* takOne = (MSG_TALKONE*)recvData;
printf("私聊消息: %s : %s\n", takOne->userName, takOne->Content);
//takOne.useName
}
break;
case FILEINFO_MSGID:
{
const MSG_SENDFILEINFO *fileInfo = (MSG_SENDFILEINFO*)recvData;
printf("文件路径:%s ,文件大小:%d\n", fileInfo->fileName, fileInfo->fileSize);
}
break;
case FILE_MSGID:
{
const MSG_SENDFILE *file = (MSG_SENDFILE*)recvData;
printf("文件内容:%s\n", file->fileBuf);
}
break;
default:
break;
}
return true;
}
数据库操作dbOperation.cpp,将对数据库得到的数据传给客户端
void DB_Login(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock) {
const LOGIN* loginMsg = (LOGIN*)recvData;
printf("登录消息:%s\t%s\n", loginMsg->userId, loginMsg->userPassword);
CString query;
query.Format(_T("select * from student_info where studentId like '%s' and studentPassword like '%s';"), loginMsg->userId, loginMsg->userPassword);
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
int ress = mysql_real_query(&sqlCon, str, strlen(str));
MYSQL_RES *res;
MYSQL_ROW row;
if (ress == 0)//检测查询成功
{
res = mysql_store_result(&sqlCon);//得到存储结果集
if (mysql_num_rows(res) == 0) {
LOGIN_RESULT loginResult;
memset(&loginResult, 0, sizeof(LOGIN_RESULT));
loginResult.msgID = LOGIN_RESULT_MSGID;
strcpy_s(loginResult.result, "loginFalse");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &loginResult, sizeof(loginResult));
send(lisSock, buff, sizeof(buff), 0);
}
else
{
LOGIN_RESULT loginResult;
memset(&loginResult, 0, sizeof(LOGIN_RESULT));
loginResult.msgID = LOGIN_RESULT_MSGID;
strcpy_s(loginResult.result, "loginTrue");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &loginResult, sizeof(loginResult));
send(lisSock, buff, sizeof(buff), 0);
}
}
}
void DB_Register(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock) {
const REGISTER* registerMsg = (REGISTER*)recvData;
printf("注册消息:%s\t%s\t%s\n", registerMsg->userId, registerMsg->userName, registerMsg->userPassword);
CString query;
query.Format(_T("insert into student_info values('%s','%s','%s');"), registerMsg->userId, registerMsg->userName, registerMsg->userPassword);
//AfxMessageBox(query.GetBuffer(0));
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
if (mysql_real_query(&sqlCon, str, strlen(str)))
{
REGISTER_RESULT registerResult;
memset(®isterResult, 0, sizeof(REGISTER_RESULT));
registerResult.msgID = REGISTER_RESULT_MSGID;
strcpy_s(registerResult.result, "registerFalse");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, ®isterResult, sizeof(registerResult));
send(lisSock, buff, sizeof(buff), 0);
}
else
{
REGISTER_RESULT registerResult;
memset(®isterResult, 0, sizeof(REGISTER_RESULT));
registerResult.msgID = REGISTER_RESULT_MSGID;
strcpy_s(registerResult.result, "registerTrue");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, ®isterResult, sizeof(registerResult));
send(lisSock, buff, sizeof(buff), 0);
}
}
void DB_AllCourse(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock)//查看所有课程
{
CString query;
query.Format(_T("select * from course;"));
AfxMessageBox(query.GetBuffer(0));
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
int ress = mysql_real_query(&sqlCon, str, strlen(str));
MYSQL_RES *result;
if (ress == 0)//检测查询成功
{
result = mysql_store_result(&sqlCon);//得到存储结果集
int rowCount = mysql_num_rows(result);//行数
unsigned int fieldCount = mysql_num_fields(result);//列数
//逐行发送
MYSQL_ROW row = NULL;
row = mysql_fetch_row(result);
printf("全部课程:\n");
char buff[1024] = { 0 };
int line = 0;
while (NULL != row) {
printf("%d\t%s\t%s\t%s\t%s\t%s\t%s\n",line,row[0], row[1], row[2], row[3], row[4], row[5]);
ALLCOURSE_RESULT course;
course.msgID = ALLCOURSE_RESULT_MSGID;
course.row = line;
line++;
strcpy_s(course.courseId, row[0]);
strcpy_s(course.courseName, row[1]);
strcpy_s(course.courseScore, row[2]);
strcpy_s(course.courseTime, row[3]);
strcpy_s(course.coursePeople, row[4]);
strcpy_s(course.teacherId, row[5]);
memset(buff, 0, sizeof(buff));
memcpy(buff, &course, sizeof(course));
send(lisSock, buff, sizeof(buff), 0);
row = mysql_fetch_row(result);
}
}
}
void DB_Student_Course(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock) {//查看学生所选课程
const STUDENT_COURSE* studentMsg = (STUDENT_COURSE*)recvData;
printf("查询%s学生课程:\n",studentMsg->userId);
CString query;
query.Format(_T("select *from course WHERE courseId in ( select courseId from selectcourse where studentId = '%s');"),studentMsg->userId);
//AfxMessageBox(query.GetBuffer(0));
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
int ress = mysql_real_query(&sqlCon, str, strlen(str));
MYSQL_RES *result;
if (ress == 0)//检测查询成功
{
result = mysql_store_result(&sqlCon);//得到存储结果集
int rowCount = mysql_num_rows(result);//行数
unsigned int fieldCount = mysql_num_fields(result);
MYSQL_ROW row = NULL;
row = mysql_fetch_row(result);
char buff[1024] = { 0 };
int line = 0;
while (NULL != row) {
printf("%d\t%s\t%s\t%s\t%s\t%s\t%s\n", line, row[0], row[1], row[2], row[3], row[4], row[5]);
ALLCOURSE_RESULT course;
course.msgID = STUDENT_COURSE_RESULT_MSGID;
course.row = line;
line++;
strcpy_s(course.courseId, row[0]);
strcpy_s(course.courseName, row[1]);
strcpy_s(course.courseScore, row[2]);
strcpy_s(course.courseTime, row[3]);
strcpy_s(course.coursePeople, row[4]);
strcpy_s(course.teacherId, row[5]);
memset(buff, 0, sizeof(buff));
memcpy(buff, &course, sizeof(course));
send(lisSock, buff, sizeof(buff), 0);
row = mysql_fetch_row(result);
}
}
}
void DB_Student_AddCourse(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock)//学生添加课程
{
const STUDENT_ADD_COURSE* msg = (STUDENT_ADD_COURSE*)recvData;
printf("%s学生添加%s课程\n", msg->userId, msg->courseId);
CString query;
query.Format(_T("insert into selectcourse values('%s','%s');"), msg->userId,msg->courseId);
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
int res = mysql_real_query(&sqlCon, str, strlen(str));
if (res == 0)
{
STUDENT_ADD_COURSE_RESULT addCourseResult;
memset(&addCourseResult, 0, sizeof(STUDENT_ADD_COURSE_RESULT));
addCourseResult.msgID = STUDENT_ADD_COURSE_RESULT_MSGID;
strcpy_s(addCourseResult.result, "addCourseTrue");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &addCourseResult, sizeof(addCourseResult));
send(lisSock, buff, sizeof(buff), 0);
}
else
{
STUDENT_ADD_COURSE_RESULT addCourseResult;
memset(&addCourseResult, 0, sizeof(STUDENT_ADD_COURSE_RESULT));
addCourseResult.msgID = STUDENT_ADD_COURSE_RESULT_MSGID;
strcpy_s(addCourseResult.result, "addCourseFalse");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &addCourseResult, sizeof(addCourseResult));
send(lisSock, buff, sizeof(buff), 0);
}
}
void DB_Student_DeleteCourse(const char* recvData, int len, MYSQL &sqlCon, SOCKET lisSock) {
const STUDENT_DELETE_COURSE* msg = (STUDENT_DELETE_COURSE*)recvData;
printf("%s学生删除%s课程\n", msg->userId, msg->courseId);
CString query;
query.Format(_T("delete from selectcourse where studentId = '%s' and courseId = '%s';"), msg->userId, msg->courseId);
const char *str = (char*)query.GetBuffer(0);//要将属性中字符类型改为多字节
int res = mysql_real_query(&sqlCon, str, strlen(str));
if (res == 0)
{
STUDENT_DELETE_COURSE_RESULT deleteCourseResult;
memset(&deleteCourseResult, 0, sizeof(STUDENT_DELETE_COURSE_RESULT));
deleteCourseResult.msgID = STUDENT_DELETE_COURSE_RESULT_MSGID;
strcpy_s(deleteCourseResult.result, "deleteCourseTrue");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &deleteCourseResult, sizeof(deleteCourseResult));
send(lisSock, buff, sizeof(buff), 0);
}
else
{
STUDENT_DELETE_COURSE_RESULT deleteCourseResult;
memset(&deleteCourseResult, 0, sizeof(STUDENT_DELETE_COURSE_RESULT));
deleteCourseResult.msgID = STUDENT_DELETE_COURSE_RESULT_MSGID;
strcpy_s(deleteCourseResult.result, "deleteCourseFalse");
char buff[1024] = { 0 };
memset(buff, 0, sizeof(buff));
memcpy(buff, &deleteCourseResult, sizeof(deleteCourseResult));
send(lisSock, buff, sizeof(buff), 0);
}
}
在客户端中,写一个继承自CSOCKET的类,并实现其OnRecevie方法:
#include "../select/netStruct.h"
extern HWND login_hwnd;
extern HWND student_hwnd;
// clientSock
clientSock::clientSock()
{
}
clientSock::~clientSock()
{
}
// clientSock 成员函数
void clientSock::OnReceive(int nErrorCode)
{
// TODO: 在此添加专用代码和/或调用基类
char recvData[1024] = {0};
memset(recvData, 0, sizeof(recvData));
int nLen = Receive(recvData, sizeof(recvData));
short msgID = *(short*)recvData;
switch (msgID)
{
case LOGIN_RESULT_MSGID:
{
LOGIN_RESULT loginMsg;
memset(&loginMsg, 0, sizeof(LOGIN_RESULT));
memcpy(&loginMsg,recvData, sizeof(loginMsg));//注意sizeof中要是转换的结构体大小
if (strcmp(loginMsg.result, "loginTrue") == 0) {
AfxMessageBox("登录成功!");
::PostMessage(login_hwnd, LOGINMSG, 0, (LPARAM)recvData);//自定义消息,用于将内容传到对话框
}
else
{
AfxMessageBox("登录失败!");
}
}
break;
case REGISTER_RESULT_MSGID:
{
REGISTER_RESULT registerMsg;
memset(®isterMsg, 0, sizeof(LOGIN_RESULT));
memcpy(®isterMsg, recvData, sizeof(registerMsg));//注意sizeof中要是转换的结构体大小
if (strcmp(registerMsg.result, "registerTrue") == 0) {
AfxMessageBox("注册成功!");
}
else
{
AfxMessageBox("注册失败!");
}
}
break;
case ALLCOURSE_RESULT_MSGID://显示所有课程
{
::PostMessage(student_hwnd, SHOW_COURSE_MSG, 0, (LPARAM)recvData);//自定义消息
}
break;
case STUDENT_COURSE_RESULT_MSGID://显示学生已选课程
{
::PostMessage(student_hwnd, SHOW_MYCOURSE_MSG, 0, (LPARAM)recvData);//自定义消息
}
break;
case STUDENT_ADD_COURSE_RESULT_MSGID://学生添加课程结果
{
STUDENT_ADD_COURSE_RESULT addMsg;
memset(&addMsg, 0, sizeof(STUDENT_ADD_COURSE_RESULT));
memcpy(&addMsg, recvData, sizeof(addMsg));//注意sizeof中要是转换的结构体大小
if (strcmp(addMsg.result, "addCourseTrue") == 0) {
::PostMessage(student_hwnd, UPDATE_DATA_MSG, 0, 0);//自定义消息
AfxMessageBox("选课成功!");
}
else
{
AfxMessageBox("选课失败!");
}
}
break;
case STUDENT_DELETE_COURSE_RESULT_MSGID://学生添加课程结果
{
STUDENT_DELETE_COURSE_RESULT deleteMsg;
memset(&deleteMsg, 0, sizeof(STUDENT_DELETE_COURSE_RESULT));
memcpy(&deleteMsg, recvData, sizeof(deleteMsg));//注意sizeof中要是转换的结构体大小
if (strcmp(deleteMsg.result, "deleteCourseTrue") == 0) {
::PostMessage(student_hwnd, UPDATE_DATA_MSG, 0, 0);//自定义消息
AfxMessageBox("删除课程成功!");
}
else
{
AfxMessageBox("删除课程失败!");
}
}
break;
}
CSocket::OnReceive(nErrorCode);
}