写了一个小项目,图书馆系统,功能如下:
1,添加书籍
2,删除书籍(可删除还没外借的书籍)
3,读者借书
4,读者还书
5,按书籍登入号查看信息(每一本书的书籍登入号唯一,如有5本相同书名作者的书,那就有5个不同的书籍登入号)
6,查询所有图书信息(可以直接查看到同本书在图书馆中的剩余和借出情况)
7,查看指定读者的借书详情
8,注册新读者
9,查看所有书籍信息(可以详细到每个登入号和此登入号书籍的借阅情况:如谁借的,借阅日期)
采用客户端和服务器模式,服务器端接收客户端,一旦接收到便启用线程,然后相应来自此客户端的不同请求
server端
serverHead.h
#ifndef SERVERHEAD
#define SERVERHEAD
#include <iostream>
#include <string>
#include <cstdlib>
#include <list>
#include <iterator>
#include <fstream>
#include <cstring>
#include <thread>
#include<WINSOCK2.H>
#include <mysql.h>
#pragma comment(lib,"ws2_32.lib")
struct infoData
{
int flag; //各种命令
int borFlag; //借阅情况1表示借出,0表示未出借
char enterName[20]; //书籍登入号,一本份
char bookName[50]; //书籍名
char bookNum[20]; //书编号
char bookWriter[50]; //书作者
int remainBook; //最初设置的库存
char readerName[50]; //借书者
char readerNum[50]; //借书证
char borrowTime[30]; //借书时间
int remain; //库中还剩此书数量
int lend; //从库中借出的此书数量
};
class Book_mysql
{
public:
Book_mysql();
bool connectAndCreate(); //链接创建数据库和表
bool selectWhetherEmpty(); //检测是否为空表
bool testTheBookWhetherExist(const infoData& Data); //判断书籍存在
bool insertTo(infoData & Data); //插入书籍
int deleteFrom(infoData & Data); //删除相应书籍
bool readerBorrowBook(infoData & Data); //读者借书
int readerReturnBook(infoData & Data); //还书
bool whetherSurpass(infoData & Data); //判断是否超过借书上限(上限一本书最多借两本)
bool selectBookByEntername(infoData & Data); //通过书籍登入号查询书籍
void displayInformation(infoData & Data, const SOCKET& sClient);//打印(笼统)
void showTheReaderBook(infoData & Data, SOCKET & sClient);//打印指定读者借书情况
void DISPLAY(infoData & Data, SOCKET& sClient); //打印(详细)
private:
char user[30]; //登陆名字
char pswd[10]; //密码
char host[20]; //表示本地数据库
unsigned int port; //端口
MYSQL myCont;
MYSQL_RES *result;
MYSQL_ROW sql_row;
int res;
};
class Reader_mysql
{
public:
Reader_mysql();
bool connectAndCreate();
bool testTheReaderWhetherExist(infoData & Data);//检测该读者是否已经存在
void insertTo(infoData & Data); //注册
bool readerBorrowBook(); //借书
bool readerReturnBook(); //还书
private:
char user[30]; //登陆名字
char pswd[10]; //密码
char host[20]; //表示本地数据库
unsigned int port;
MYSQL myCont;
MYSQL_RES *result;
MYSQL_ROW sql_row;
int res;
};
class serverSocket
{
public:
serverSocket(int port);
~serverSocket();
SOCKET serverAccpetSocket();//阻塞accept
private:
WSADATA wsd;
SOCKET sServer; //客户端套接字 用来监听
std::list<SOCKET> listScli; //客户端套接字 用链表来接收,接送一个放一个
SOCKET temp; //用来存放中间值
SOCKADDR_IN addrServ; //服务器地址
};
void addBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql);
void deleteBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql);
void borrowBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql, Reader_mysql & reader_mysql);
void returnBook(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql, Reader_mysql & reader_mysql);
void searchBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql);
void displayAllBook(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql);
void DISPLAY(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql);
void showTheReaderBook(infoData & Data, SOCKET & sClient, Book_mysql & book_mysql, Reader_mysql & reader_mysql);
void setNewReader(infoData & Data, const SOCKET & sClient, Reader_mysql & reader_mysql);
void clientSocketThreadFunction(SOCKET sClient);
#endif
套接字类的实现
serverSocket.cpp
#include "serverHead.h"
serverSocket::serverSocket(int port)
{
//初始化套结字动态库
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
std::cout << "WSAStartup failed!" << std::endl;
return;
}
//开始创建服务端socket
//创建套接字 AF_INET:ipv4 SOCK_STREAM:使用tcp
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
std::cout << "socket failed!" << std::endl;
return;
}
//服务器套接字地址
addrServ.sin_family = AF_INET;//IPv4
addrServ.sin_port = htons(port);//设置端口 建议大于1024
addrServ.sin_addr.s_addr = INADDR_ANY; //表示接受任何客户端的请求
//绑定套接字 绑定服务端socket 和 端口
int ret = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == ret)
{
std::cout << "bind failed!" << std::endl;
return;
}
//开始监听
ret = listen(sServer, 10);
if (SOCKET_ERROR == ret)
{
std::cout << "listen failed!" << std::endl;
return;
}
}
serverSocket::~serverSocket()
{
closesocket(sServer); //关闭套接字
WSACleanup(); //释放套接字资源;
}
SOCKET serverSocket::serverAccpetSocket()
{
//接受客户端请求
sockaddr_in addrClient;
int addrClientlen = sizeof(addrClient);
temp = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen);
if (INVALID_SOCKET == temp)
{
std::cout << "accept failed!" << std::endl;
return -1;
}
listScli.push_front(temp);
return temp;
}
MySQL中书籍表的实现
bookMysql.cpp
#include "serverHead.h"
Book_mysql::Book_mysql()
{
strcpy_s(user, "root");
strcpy_s(pswd, "123456");
strcpy_s(host, "localhost");
port = 3306;
mysql_init(&myCont);
if (mysql_real_connect(&myCont, host, user, pswd, "mysql", port, NULL, 0))//先链接自带的数据库,以便后面创建专属数据库
{
res = mysql_query(&myCont, "create database if not exists zhanghsun");
mysql_query(&myCont, "SET NAMES GBK");
if (res)
{
std::cout << "创建库失败" << std::endl;
system("pause");
exit(-1);;
}
res = mysql_query(&myCont, "use zhanghsun");
if (res)
{
std::cout << "use 失败" << std::endl;
system("pause");
exit(-1);
}
char order[1024];
sprintf_s(order, "create table IF NOT EXISTS m_book(书籍登入号 char(10) not null, 书名 char(20) default null, 书编号 char(20) default null, 书作者 char(50) default null, 借阅 int default 0, 读者名 char(20) default '%s', 读者借书号 char(20) default '%s', 借阅时间 char(20) default '%s')", "无", "无", "无");
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "创建表失败" << std::endl;
system("pause");
exit(-1);
}
}
else
{
std::cout << "链接失败" << std::endl;
system("pause");
exit(-1);
}
}
//判断指定书籍是否存在
bool Book_mysql::testTheBookWhetherExist(const infoData& Data)
{
char order[1024];
//检测是否存在该书
sprintf_s(order, "SELECT * FROM m_book WHERE 书名='%s' and 书作者 = '%s'", Data.bookName, Data.bookWriter);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if (sql_row = mysql_fetch_row(result))//如果查询不为空
{
return 1;//已有该书
}
}
}
else
{
std::cout << "查询失败" << std::endl;
system("pause");
exit(-1);
}
return 0;//没有该书
}
//插入书籍操作
bool Book_mysql::insertTo(infoData & Data)
{
char order[1024];
sprintf_s(order, "insert into m_book (书籍登入号,书名,书编号,书作者) values('%s','%s','%s','%s')", Data.enterName,Data.bookName, Data.bookNum, Data.bookWriter);
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "插入失败" << std::endl;
system("pause");
exit(-1);
}
return 1;
}
//判断表是否为空
bool Book_mysql::selectWhetherEmpty()
{
char order[1024];
sprintf_s(order, "SELECT * FROM m_book");
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if (sql_row = mysql_fetch_row(result))//获取具体的数据
{
return 0;//表不为空
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
return 1;//表为空
}
//判断该读者要借书籍是否超出上限
bool Book_mysql::whetherSurpass(infoData & Data)
{
char order[1024];
int num = 0;
sprintf_s(order, "select 读者名,读者借书号 from m_book where 书名 = '%s' and 书作者 = '%s'", Data.bookName, Data.bookWriter);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
while (sql_row = mysql_fetch_row(result))//获取具体的数据
{
if (strcmp(Data.readerName, sql_row[0]) == 0
&& strcmp(Data.readerNum, sql_row[1]) == 0)
{
++num;
}
if (num >= 2)
{
return 1;//已达上限
}
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
return 0;//没超
}
//删除书籍
int Book_mysql::deleteFrom(infoData & Data)
{
char order[1024];
int flag = 0;
sprintf_s(order, "SELECT * FROM m_book WHERE 书名='%s' AND 书作者 = '%s' AND 借阅 = '%d'", Data.bookName, Data.bookWriter, 0);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
while (sql_row = mysql_fetch_row(result))//获取具体的数据
{
flag = 1;
std::cout << "删除登入号:" << sql_row[0] << std::endl;
//根据得到的登入号一一删除
sprintf_s(order, "DELETE FROM m_book WHERE 书籍登入号 = '%s'", sql_row[0]);
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "删除failed" << std::endl;
system("pause");
exit(-1);
}
}
if (flag == 0)
{
return -1;//全借出
}
else if (flag == 1)
{
return 1;//删除了相关书籍
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
}
//读者借阅书籍
bool Book_mysql::readerBorrowBook(infoData & Data)
{
char order[1024];
sprintf_s(order, "SELECT 书籍登入号 FROM m_book WHERE 书名='%s' AND 书作者 = '%s' AND 借阅 = '%d'", Data.bookName, Data.bookWriter, 0);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if(sql_row = mysql_fetch_row(result))//获取具体的数据
{
std::cout << "借的书的登入号:" << sql_row[0] << std::endl;
sprintf_s(order, "UPDATE m_book SET 借阅 = '%d',读者名 = '%s',读者借书号 = '%s', 借阅时间 = NOW() WHERE 书籍登入号 = '%s'", 1, Data.readerName,Data.readerNum, sql_row[0]);
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "更新failed" << std::endl;
system("pause");
exit(-1);
}
}
else
{
return 0;//书全借光
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
return 1;//借书成功
}
//还书
int Book_mysql::readerReturnBook(infoData & Data)
{
char order[1024];
sprintf_s(order, "SELECT * FROM m_book WHERE 书籍登入号='%s'", Data.enterName);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if (sql_row = mysql_fetch_row(result))//获取具体的数据
{
std::cout << "登入号:" << sql_row[0] << std::endl;
sprintf_s(order, "UPDATE m_book SET 借阅 = 0, 读者名 = '%s', 读者借书号 = '%s', 借阅时间 = '%s' WHERE 书籍登入号 = '%s'","无", "无", "无", Data.enterName);
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "更新failed" << std::endl;
system("pause");
exit(-1);
}
}
else
{
return 0;//没找到该登入号
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
return 1;//成功
}
//更具书籍登入号查询书籍信息
bool Book_mysql::selectBookByEntername(infoData & Data)
{
char order[1024];
int flag = 0;
sprintf_s(order, "SELECT * FROM m_book WHERE 书籍登入号='%s'", Data.enterName);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if(sql_row = mysql_fetch_row(result))//获取具体的数据
{
flag = 1;
strcpy_s(Data.enterName, sql_row[0]);
strcpy_s(Data.bookName, sql_row[1]);
strcpy_s(Data.bookNum, sql_row[2]);
strcpy_s(Data.bookWriter, sql_row[3]);
if (atoi(sql_row[4]) == 1)
{
Data.borFlag = 1;
strcpy_s(Data.readerName, sql_row[5]);
strcpy_s(Data.readerNum, sql_row[6]);
strcpy_s(Data.borrowTime, sql_row[7]);
}
else
{
Data.borFlag = 0;
}
}
if (flag == 0)
{
return 0;//登入号没找到
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
return 1;
}
//笼统打印
void Book_mysql::displayInformation(infoData & Data, const SOCKET& sClient)
{
char order[1024];
char tempName[30];
char tempWriter[30];
int lend = 0;
int remain = 0;
sprintf_s(order, "SELECT 书名,书编号,书作者 FROM m_book");
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
while (sql_row = mysql_fetch_row(result))//获取具体的数据
{
strcpy_s(Data.bookName, sql_row[0]);
strcpy_s(Data.bookNum, sql_row[1]);
strcpy_s(Data.bookWriter, sql_row[2]);
if (strcmp(Data.bookName, tempName) == 0
&& strcmp(Data.bookWriter, tempWriter) == 0)//相同书籍不予计算
{
continue;
}
lend = 0;
remain = 0;
char _order[1024];//已借书情况
sprintf_s(_order, "SELECT count(*) FROM m_book where 书名= '%s' and 书作者 = '%s' and 借阅 = 1", Data.bookName, Data.bookWriter);
res = mysql_query(&myCont, _order);
if (!res)
{
MYSQL_RES *_result = mysql_store_result(&myCont);
if (_result)
{
MYSQL_ROW _sql_row;
while (_sql_row = mysql_fetch_row(_result))//获取具体的数据
{
lend = atoi(_sql_row[0]);
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
//剩余没借情况
sprintf_s(_order, "SELECT count(*) FROM m_book where 书名= '%s' and 书作者 = '%s' and 借阅 = 0", Data.bookName, Data.bookWriter);
res = mysql_query(&myCont, _order);
if (!res)
{
MYSQL_RES *_result = mysql_store_result(&myCont);
if (_result)
{
MYSQL_ROW _sql_row;
while (_sql_row = mysql_fetch_row(_result))//获取具体的数据
{
remain = atoi(_sql_row[0]);
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
Data.lend = lend;
Data.remain = remain;
if (strcmp(Data.bookName, tempName) != 0
&& strcmp(Data.bookWriter, tempWriter) != 0)
{
Data.flag = 0;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
strcpy_s(tempName, Data.bookName);
strcpy_s(tempWriter, Data.bookWriter);
}
}
}
else
{
std::cout << "查询failed" << std::endl;
system("pause");
exit(-1);
}
Data.flag = 1;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
//打印指定读者借书情况
void Book_mysql::showTheReaderBook(infoData & Data, SOCKET & sClient)
{
char order[1024];
int flag = 0;
sprintf_s(order, "select 书籍登入号,书名,书编号,书作者,借阅时间 from m_book where 读者名 = '%s' and 读者借书号 = '%s';", Data.readerName, Data.readerNum);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
while (sql_row = mysql_fetch_row(result))//如果查询不为空
{
flag = 1;
strcpy_s(Data.enterName, sql_row[0]);
strcpy_s(Data.bookName, sql_row[1]);
strcpy_s(Data.bookNum, sql_row[2]);
strcpy_s(Data.bookWriter, sql_row[3]);
strcpy_s(Data.borrowTime, sql_row[4]);
Data.flag = 6;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
}
}
else
{
std::cout << "查询失败" << std::endl;
system("pause");
exit(-1);
}
if (flag == 0)
{
Data.flag = 0;//没有借书
send(sClient, (char*)&Data, sizeof(Data), 0);
}
Data.flag = -1;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
//打印(详细)
void Book_mysql::DISPLAY(infoData & Data, SOCKET& sClient)
{
char order[1024];
int flag = 0;
int i = 0;
sprintf_s(order, "select * from m_book");
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
while (sql_row = mysql_fetch_row(result))//如果查询不为空
{
flag = 1;
strcpy_s(Data.enterName, sql_row[0]);
strcpy_s(Data.bookName, sql_row[1]);
strcpy_s(Data.bookNum, sql_row[2]);
strcpy_s(Data.bookWriter, sql_row[3]);
if (atoi(sql_row[4]) == 1)
{
Data.borFlag = 1;
strcpy_s(Data.readerName, sql_row[5]);
strcpy_s(Data.readerNum, sql_row[6]);
strcpy_s(Data.borrowTime, sql_row[7]);
}
else
{
Data.borFlag = 0;
}
Data.flag = 6;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
}
if (flag == 0)//没有结果
{
Data.flag = -2;
send(sClient, (char*)&Data, sizeof(Data), 0);
}
}
Data.flag = -1;//打印退出flag
send(sClient, (char*)&Data, sizeof(Data), 0);
}
MySQL读者表的实现
readerMysql.cpp
#include "serverHead.h"
Reader_mysql::Reader_mysql()
{
strcpy_s(user, "root");
strcpy_s(pswd, "123456");
strcpy_s(host, "localhost");
port = 3306;
mysql_init(&myCont);
if (mysql_real_connect(&myCont, host, user, pswd, "mysql", port, NULL, 0))
{
res = mysql_query(&myCont, "create database if not exists zhanghsun");
mysql_query(&myCont, "SET NAMES GBK");
if (res)
{
std::cout << "创建库失败" << std::endl;
system("pause");
exit(-1);
}
res = mysql_query(&myCont, "use zhanghsun");
if (res)
{
std::cout << "use 失败" << std::endl;
system("pause");
exit(-1);
}
char order[1024];
sprintf_s(order, "create table IF NOT EXISTS m_reader(读者名 char(20) default null, 读者借书号 char(20) default null)");
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "创建表failed" << std::endl;
system("pause");
exit(-1);
}
}
else
{
std::cout << "链接失败" << std::endl;
system("pause");
exit(-1);
}
}
//判断是否重复注册
bool Reader_mysql::testTheReaderWhetherExist(infoData & Data)
{
char order[1024];
sprintf_s(order, "select * from m_reader where 读者名 = '%s' and 读者借书号 = '%s'", Data.readerName, Data.readerNum);
res = mysql_query(&myCont, order);
if (!res)
{
result = mysql_store_result(&myCont);
if (result)
{
if (sql_row = mysql_fetch_row(result))//如果查询不为空
{
return 1;//有该读者
}
}
}
else
{
std::cout << "查询失败" << std::endl;
system("pause");
exit(-1);
}
return 0;//没有此人
}
//插入新读者
void Reader_mysql::insertTo(infoData & Data)
{
char order[102];
sprintf_s(order, "insert into m_reader (读者名, 读者借书号) values('%s','%s')", Data.readerName, Data.readerNum);
res = mysql_query(&myCont, order);
if (res)
{
std::cout << "插入失败" << std::endl;
system("pause");
exit(-1);
}
//else 注册成功
}
服务器端总实现
server.cpp
#include "serverHead.h"
//增加书籍
void addBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql)
{
std::cout << "客户端 " << sClient << " 正在录入书籍 !" << std::endl;
if (book_mysql.testTheBookWhetherExist(Data))//数据库中判断该书是否已经存在
{
std::cout << "客户端" << sClient << " 添加书籍重复已退回" << std::endl;
Data.flag = -1;
send(sClient, (char*)&Data, sizeof(Data), 0);
return;
}
//按库存随机每本书的登入号并插入
srand((unsigned)time(NULL));//通过时间来随机登入号
for (int i = 0; i < Data.remainBook; i++)
{
int x = rand() % 1000;
_itoa_s(x, Data.enterName, 10);
book_mysql.insertTo(Data);//在数据库中插入
}
Data.flag = 0;
send(sClient, (char*)&Data, sizeof(Data), 0);
std::cout << "客户端 " << sClient << " 录入书籍成功 !" << std::endl;
}
//删除书籍
void deleteBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql)
{
std::cout << "客户端 " << sClient << " 正在删除书籍" << std::endl;
int flag = 0;
if (!(book_mysql.testTheBookWhetherExist(Data)))//首先判断该书是否存在
{
std::cout << "没有该书" << std::endl;
Data.flag = -1;
send(sClient, (char*)&Data, sizeof(Data), 0);
return;
}
//删除
switch (book_mysql.deleteFrom(Data))
{
case -1:
Data.flag = -2;
send(sClient, (char*)&Data, sizeof(Data), 0);
std::cout << "该书全部出借,无法进行删除" << std::endl;
break;
case 1:
Data.flag = 0;
send(sClient, (char*)&Data, sizeof(Data), 0);
std::cout << "已删除此书的所有未出借书籍" << std::endl;
break;
}
}
//借阅书籍
void borrowBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql, Reader_mysql & reader_mysql)
{
std::cout << "客户端 " << sClient << " 正在借阅书籍" << std::endl;
//判断该读者是否存在
switch (reader_mysql.testTheReaderWhetherExist(Data))
{
case 0:Data.flag = -1; send(sClient, (char*)&Data, sizeof(Data), 0); return;//没有找到该读者,直接return
case 1:Data.flag = 0; send(sClient, (char*)&Data, sizeof(Data), 0); break;//找到该读者,继续操作
}
recv(sClient, (char*)&Data, sizeof(Data), 0);
if (book_mysql.selectWhetherEmpty())
{
std::cout << "未录入任何书籍" << std::endl;
Data.flag = -1;
send(sClient, (char*)&Data, sizeof(Data), 0);
return;
}
if (!(book_mysql.testTheBookWhetherExist(Data)))
{
Data.flag = -2;
std::cout << "没有这本书" << std::endl;
send(sClient, (char*)&Data, sizeof(Data), 0);
return;
}
//判断是否多借
if (!(book_mysql.whetherSurpass(Data)))
{
switch (book_mysql.readerBorrowBook(Data))
{
case 1:Data.flag = 0; break;//借书成功
case 0:Data.flag = -3; break;//书全借光
}
}
else
{
Data.flag = -4;//借此书已达上限
}
send(sClient, (char*)&Data, sizeof(Data), 0);
}
//归还书籍
void returnBook(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql, Reader_mysql & reader_mysql)
{
std::cout << "客户端 " << sClient << " 正在归还书籍" << std::endl;
showTheReaderBook(Data, sClient, book_mysql, reader_mysql);
recv(sClient, (char*)&Data, sizeof(Data), 0);
switch (book_mysql.readerReturnBook(Data))
{
case 0:std::cout << "没有找到该登入号" << std::endl; Data.flag = -1; send(sClient, (char*)&Data, sizeof(Data), 0); break;
case 1:std::cout << "还书成功" << std::endl; Data.flag = 0; send(sClient, (char*)&Data, sizeof(Data), 0); break;
}
}
//通过登入号搜索书籍
void searchBook(infoData& Data, const SOCKET& sClient, Book_mysql & book_mysql)
{
std::cout << "客户端 " << sClient << " 正在通过登入号搜索书籍" << std::endl;
switch(book_mysql.selectBookByEntername(Data))
{
case 1:send(sClient, (char*)&Data, sizeof(Data), 0);return;
case 0:Data.flag = 3; send(sClient, (char*)&Data, sizeof(Data), 0); return;
}
}
//打印书籍(笼统打印,不打印登入号)
void displayAllBook(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql)
{
std::cout << "客户端 " << sClient << " 正在打印书籍(概括)" << std::endl;
if (book_mysql.selectWhetherEmpty())
{
std::cout << "还没有录入书籍" << std::endl;
Data.flag = -1;
send(sClient, (char*)&Data, sizeof(Data), 0);
return;
}
book_mysql.displayInformation(Data, sClient);
}
//打印每一本书籍的信息(打印每一本书的详细信息)
void DISPLAY(infoData& Data, SOCKET& sClient, Book_mysql & book_mysql)
{
std::cout << "客户端 " << sClient << " 正在打印全部书籍信息" << std::endl;
book_mysql.DISPLAY(Data, sClient);
}
//打印指定读者的借书情况
void showTheReaderBook(infoData & Data, SOCKET & sClient, Book_mysql & book_mysql,Reader_mysql & reader_mysql)
{
std::cout << "客户端 " << sClient << " 正在打印指定读者的借书情况" << std::endl;
switch (reader_mysql.testTheReaderWhetherExist(Data))
{
case 0:Data.flag = -1; send(sClient, (char*)&Data, sizeof(Data), 0); return;//没有找到该读者,直接return
case 1:Data.flag = 0; send(sClient, (char*)&Data, sizeof(Data), 0); break;//找到该读者,继续操作
}
book_mysql.showTheReaderBook(Data, sClient);
}
//注册新的读者
void setNewReader(infoData & Data, const SOCKET & sClient, Reader_mysql & reader_mysql)
{
std::cout << "客户端 " << sClient << " 正在注册新读者" << std::endl;
switch (reader_mysql.testTheReaderWhetherExist(Data))
{
case 1:Data.flag = -1; break;//已有该读者
case 0:Data.flag = 1; reader_mysql.insertTo(Data); break;//注册成功
}
send(sClient, (char*)&Data, sizeof(Data), 0);
}
//线程
void clientSocketThreadFunction(SOCKET sClient)
{
Book_mysql book_mysql;
Reader_mysql reader_mysql;
//对客户端的数据进行解析
while (true)
{
infoData Data;
int ret = recv(sClient, (char*)&Data, sizeof(Data), 0);
if (SOCKET_ERROR == ret)
{
std::cout << sClient << "可能下线" << std::endl;
return;
}
int flag = 0;
switch (Data.flag)//错误:控制传输跳过的实例化,方法,加{}
{
//增加书籍
case 1:addBook(Data, sClient, book_mysql); break;
//删除书籍
case 2:deleteBook(Data, sClient, book_mysql); break;
//借书
case 3:borrowBook(Data, sClient, book_mysql, reader_mysql); break;
//还书
case 4:returnBook(Data, sClient, book_mysql, reader_mysql); break;
//搜索借书者
case 5: searchBook(Data, sClient, book_mysql); break;
//浏览所有书籍信息
case 6: displayAllBook(Data, sClient, book_mysql); break;
//查看登入读者的借书情况
case 7:showTheReaderBook(Data, sClient,book_mysql, reader_mysql); break;
//注册
case 8:setNewReader(Data, sClient,reader_mysql); break;
//退出flag
case 9: flag = 1; break;
//所有书被借情况一览表
case -10:DISPLAY(Data, sClient, book_mysql); break;
default:std::cout << "输入错误 请重新输入:" << std::endl;
}
if (flag == 1)
{
std::cout << "客户端 " << sClient << " 下线" << std::endl;
break;
}
}
}
int main(int argc, char* argv[])
{
serverSocket mySocket(8888);
while (1)
{
SOCKET sClient = mySocket.serverAccpetSocket();
if (sClient == -1)
{
continue;
}
else
{
std::cout << "接收到一个客户端 :" << sClient << std::endl;
}
std::thread t1(clientSocketThreadFunction, sClient);//启用线程
t1.detach();
}
return 0;
}
client
头文件
clientHead.h
#ifndef CLIENTHEAH
#define CLIENTHEAH
#include <WINSOCK2.H>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
struct infoData
{
int flag; //各种命令
int borflag; //借阅情况1表示借出,0表示未出借
char enter_name[20]; //书籍登入号,一本份
char book_name[50]; //书籍名
char book_num[20]; //书编号
char book_writer[50]; //书作者
int remain_book; //最初设置的库存
char reader_name[50]; //借书者
char reader_num[50]; //借书证
char borrow_time[30]; //借书时间
int remain; //库中还剩此书数量
int lend; //从库中借出的此书数量
};
class clientSocket
{
public:
clientSocket(string ipAdress, short port);
~clientSocket();
bool connectToServer();
void receiveData(infoData & data);
void sendData(infoData & data);
private:
WSADATA wsd; //WSADATA变量
SOCKET sClient; //客户端套接字
SOCKADDR_IN servAddr; //服务器地址
int ret; //返回值
};
void menu();
void tapAnyKeyNext();
int addBook(infoData & Data, clientSocket & mySocket);
int displayAllbook(infoData Data, clientSocket & mySocket);
int deleteBook(infoData & Data, clientSocket & mySocket);
int borrowBook(infoData & Data, clientSocket & mySocket);
int returnBook(infoData & Data, clientSocket & mySocket);
int searchBook(infoData & Data, clientSocket & mySocket);
int showTheReaderBook(infoData & Data, clientSocket & mySocket);
int setNewReader(infoData & Data, clientSocket & mySocket);
void DISPLAY(infoData & Data, clientSocket & mySocket);
#endif
套接字类的实现
mySocket.cpp
#include "clientHead.h"
clientSocket::clientSocket(string ipAdress, short port)
{
//初始化套结字动态库
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
cout << "WSAStartup failed!" << endl;
return;
}
//创建套接字
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sClient)
{
cout << "socket failed!" << endl;
return;
}
servAddr.sin_family = AF_INET;
//如果编译通不过 属性 c++ 常规 sdl 改成否
servAddr.sin_addr.s_addr = inet_addr(ipAdress.c_str());//设置服务端地址 这里表示本机
servAddr.sin_port = htons(port);
int nServAddlen = sizeof(servAddr);
}
bool clientSocket::connectToServer()
{
//连接服务器
ret = connect(sClient, (LPSOCKADDR)&servAddr, sizeof(servAddr));
if (SOCKET_ERROR == ret)
{
cout << "connect failed!" << endl;
system("pause");
return false;
}
//成功建立连接 可以开始通信了
return true;
}
void clientSocket::sendData(infoData & Data)
{
//向服务器发送数据
ret = send(sClient, (char*)&Data, sizeof(Data), 0);
if (SOCKET_ERROR == ret)
{
cout << "send failed!" << endl;
return;
}
}
void clientSocket::receiveData(infoData & Data)
{
// 接收服务器端的数据
recv(sClient, (char*)&Data, sizeof(Data), 0);
/*if (ret < 0)
{
cout << "recv failed" << endl;
return;
}*/
}
clientSocket::~clientSocket()
{
closesocket(sClient); //关闭套接字
WSACleanup(); //释放套接字资源
}
客户端总实现
client
#include "clientHead.h"
void menu()
{
cout << "*****************************" << endl;
cout << endl;
cout << "1.录入书籍"<<endl;
cout << "2.删除书籍" << endl;
cout << "3.借书" << endl;
cout << "4.还书" << endl;
cout << "5.按书籍登入号查看信息" <<endl;
cout << "6.查询所有图书信息" << endl;
cout << "7.查看你的借书详情" << endl;
cout << "8.注册" << endl;
cout << "9.退出" << endl;
cout << "-10.查看所有书籍信息" << endl;
cout << endl;
cout << "*****************************" << endl;
}
//增加书籍
int addBook(infoData & Data, clientSocket & mySocket)
{
Data.flag = 1;
cout << "开始录入书籍 !" << endl;
cout << "输入书名:";
cin >> Data.book_name;
cout << "输入书编号:";
cin >> Data.book_num;
cout << "输入书作者:";
cin >> Data.book_writer;
cout << "输入书库存:";
cin >> Data.remain_book;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "已有此书,请勿重复添加" << endl;
}
if (Data.flag == 0)
{
cout << "添加成功" << endl;
}
cout << "是否继续增加书籍操作? 1 : 0 ";
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
//删除书籍
int deleteBook(infoData & Data, clientSocket & mySocket)
{
if (displayAllbook(Data, mySocket))
{
tapAnyKeyNext();
return 0;
}
cout << "已经外借的那本无法删除" << endl;
cout << "输入书名:";
cin >> Data.book_name;
cout << "输入作者:";
cin >> Data.book_writer;
Data.flag = 2;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有该书" << endl;
}
else if (Data.flag == -2)
{
cout << "该书全部出借,无法进行删除" << endl;
}
else if (Data.flag == 0)
{
cout << "删除成功" << endl;
}
cout << "是否继续删除书籍操作? 1 : 0 ";
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
//借书
int borrowBook(infoData & Data, clientSocket & mySocket)
{
Data.flag = 3;
cout << "输入你的姓名:" << endl;
cin >> Data.reader_name;
cout << "输入你的借书号:" << endl;
cin >> Data.reader_num;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有找到该读者,是否重新输入?1:2" << endl;
char ch[10];
cin >> ch;
int x = atoi(ch);
switch (x)
{
case 1:return 1; break;
case 2:return 0; break;
}
}
else if (Data.flag == 0)
{
cout << "登入成功" << endl;
}
cout << "输入书籍名:";
cin >> Data.book_name;
cout << "输入书作者:";
cin >> Data.book_writer;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == 0)
{
cout << "借书成功" << endl;
}
else if (Data.flag == -1)
{
cout << "未录入任何书籍" << endl;
}
else if (Data.flag == -2)
{
cout << "没有这本书" << endl;
}
else if (Data.flag == -3)
{
cout << "该书已借光" << endl;
}
else if (Data.flag == -4)
{
cout << "借此书此书已达上限" << endl;
}
cout << "是否继续借书操作? 1 : 0 ";
while (true)
{
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
}
//还书
int returnBook(infoData & Data, clientSocket & mySocket)
{
Data.flag = 4;
cout << "输入你的姓名:" << endl;
cin >> Data.reader_name;
cout << "输入你的借书号:" << endl;
cin >> Data.reader_num;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有找到该读者,是否重新输入?1:2" << endl;
char ch[10];
cin >> ch;
int x = atoi(ch);
switch (x)
{
case 1:return 1; break;
case 2:return 0; break;
}
}
else if (Data.flag == 0)
{
cout << "登入成功" << endl;
}
cout << "您所借书如下:" << endl;
cout << endl;
mySocket.receiveData(Data);
if (Data.flag == 0)
{
cout << endl;
std::cout << "你没有借书" << std::endl;
cout << endl;
return 1;
}
while (Data.flag == 6)
{
cout << "登入号 :" << Data.enter_name << endl;
cout << "书籍名 :" << Data.book_name << endl;
cout << "书籍号 :" << Data.book_num << endl;
cout << "作者名 : " << Data.book_writer << endl;
cout << "借阅时间 :" << Data.borrow_time << endl;
cout << endl;
mySocket.receiveData(Data);
}
cout << "输入登入号还书:" << endl;
cin >> Data.enter_name;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有查询到该登入号" << endl;
}
else if (Data.flag == 0)
{
cout << "还书成功" << endl;
}
cout << "是否继续还书操作? 1 : 0 ";
while (true)
{
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
}
//打印(笼统)
int displayAllbook(infoData Data, clientSocket & mySocket)
{
Data.flag = 6;
mySocket.sendData(Data);
cout << endl;
while (true)
{
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有录入书籍" << endl;
return -1;
}
else if (Data.flag == 1)
{
break;
}
else if (Data.flag == 0)
{
cout << "书籍名 :" << Data.book_name << endl;
cout << "书籍号 :" << Data.book_num << endl;
cout << "作者名 :" << Data.book_writer << endl;
cout << "还剩余 :" << Data.remain << " 本" << endl;
cout << "已借出 :" << Data.lend <<" 本"<< endl;
cout << endl;
}
}
return 0;
}
//通过书籍登入号查找书籍信息
int searchBook(infoData & Data, clientSocket & mySocket)
{
Data.flag = 5;
cout << "请输入书籍登入号" << endl;
cin >> Data.enter_name;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == 3)
{
cout << "没有这个登入号" << endl;
tapAnyKeyNext();
return 0;
}
cout << endl;
cout << "查询结果如下" << endl;
cout << endl;
cout << "登入号 :" << Data.enter_name << endl;
cout << "书籍名 :" << Data.book_name << endl;
cout << "书籍号 :" << Data.book_num << endl;
cout << "作者名 : " << Data.book_writer << endl;
if (Data.borflag == 1)
{
cout << "**该书已被借**" << endl;
cout << "借书者 :" << Data.reader_name << endl;
cout << "借书证 :" << Data.reader_num << endl;
}
else if (Data.borflag == 0)
{
cout << "**该书没被借**" << endl;
}
cout << endl;
cout << "查询完成" << endl;
cout << "是否继续查询操作? 1 : 0 ";
while (true)
{
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
}
//查看指定读者借书情况
int showTheReaderBook(infoData & Data, clientSocket & mySocket)
{
Data.flag = 7;
cout << "输入你的姓名:" << endl;
cin >> Data.reader_name;
cout << "输入你的借书号:" << endl;
cin >> Data.reader_num;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == -1)
{
cout << "没有找到该读者,是否重新输入?1:2" << endl;
char ch[10];
cin >> ch;
int x = atoi(ch);
switch (x)
{
case 1:return 1; break;
case 2:return 0; break;
}
}
else if (Data.flag == 0)
{
cout << "登入成功" << endl;
}
mySocket.receiveData(Data);
if (Data.flag == 0)
{
cout << "你还没借书" << endl;
}
else
{
cout << endl;
cout << "查询结果如下" << endl;
cout << endl;
while (Data.flag == 6)
{
cout << "登入号 :" << Data.enter_name << endl;
cout << "书籍名 :" << Data.book_name << endl;
cout << "书籍号 :" << Data.book_num << endl;
cout << "作者名 : " << Data.book_writer << endl;
cout << "借书时间 :" << Data.borrow_time << endl;
cout << endl;
mySocket.receiveData(Data);
}
}
cout << "以上是您所有的借书情况" << endl;
cout << "是否继续此查询操作? 1 : 0 ";
while (true)
{
while (1)
{
int x;
cin >> x;
switch (x)
{
case 0:return 0;//退出
case 1:return 1;//继续
default:cout << "输入错误 请重新输入:";
}
}
}
}
//创建新读者
int setNewReader(infoData & Data, clientSocket & mySocket)
{
Data.flag = 8;
cout << "输入你的姓名:" << endl;
cin >> Data.reader_name;
cout << "输入你的借书号:" << endl;
cin >> Data.reader_num;
mySocket.sendData(Data);
mySocket.receiveData(Data);
if (Data.flag == 1)
{
cout << "注册成功" << endl;
tapAnyKeyNext();
return 0;
}
else if (Data.flag == -1)
{
cout << "名字借书号重复,是否重新输入?1:2" << endl;
char ch[10];
cin >> ch;
int x = atoi(ch);
switch (x)
{
case 1:return 1; break;
case 2:return 0; break;
}
}
}
//遍历每一本书的详情信息
void DISPLAY(infoData & Data, clientSocket & mySocket)
{
Data.flag = -10;
int i = 0;
mySocket.sendData(Data);
cout << endl;
while (true)
{
mySocket.receiveData(Data);
if (Data.flag == -2)
{
cout << "没有录入书籍" << endl;
tapAnyKeyNext();
return;
}
if (Data.flag == -1)
{
break;
}
/*std::cout << "i = " << i << std::endl;
++i;*/
cout << "登入号 :" << Data.enter_name << endl;
cout << "书籍名 :" << Data.book_name << endl;
cout << "书籍号 :" << Data.book_num << endl;
cout << "作者名 : " << Data.book_writer << endl;
if (Data.borflag == 1)
{
cout << "**该书已被借**" << endl;
cout << "借书者 :" << Data.reader_name << endl;
cout << "借书证 :" << Data.reader_num << endl;
cout << "借阅时间 :" << Data.borrow_time << endl;
}
else if (Data.borflag == 0)
{
cout << "**该书没被借**" << endl;
}
cout << endl;
}
cout << "查询完成" << endl;
cout << endl;
tapAnyKeyNext();
}
//按任意键退出
void tapAnyKeyNext()
{
while (1)
{
cout << "按任意键返回主菜单" << endl;
string x;
cin >> x;
return;
}
}
int main()
{
clientSocket mySocket("127.0.0.1", 8888);
if (!mySocket.connectToServer())
{
return 0;
}
//向服务端发送数据
while (true)
{
menu();
infoData Data;
char ch[20];
cout << "输入操作:";
cin >> ch;
int x = atoi(ch);
int flag = 0;
switch (x)
{
case 1:
{
while (1)
{
if (addBook(Data, mySocket) == 0)
{
break;
}
}
} break;
case 2:
{
while (1)
{
if (deleteBook(Data, mySocket) == 0)
{
break;
}
}
}break;
case 3:
{
while (1)
{
if (borrowBook(Data, mySocket) == 0)
{
break;
}
}
}break;
case 4:
{
while (1)
{
if (returnBook(Data, mySocket) == 0)
{
break;
}
}
}break;
case 5:
{
while (1)
{
if (searchBook(Data, mySocket) == 0)
{
break;
}
}
}break;
case 6:displayAllbook(Data, mySocket); tapAnyKeyNext(); break;
case 7:
{
while (1)
{
if (showTheReaderBook(Data, mySocket) == 0)
{
break;
}
}
}break;
case 8:
{
while (1)
{
if (setNewReader(Data, mySocket) == 0)
{
break;
}
}
}break;
case 9:flag = 1; break;
case -10:DISPLAY(Data, mySocket); break;
default:cout << "输入错误 请重新输入:" << endl;
}
if (flag == 1)
{
Data.flag = 9;
mySocket.sendData(Data);
break;
}
}
WSACleanup();
return 0;
}
平台:vs2013
MySQL5.7
综合了MySQL,网络通信,线程等相关知识,看了不少书,但难免有些幼稚的地方请见谅