这几天一直在构思银行管理系统的项目,这个项目是基于C++开发的,其主要功能有以下几点:登录界面:职员登录,退出 主菜单中包括:1、客户开户 2、存款 3、取款 4、转账 5、查看账单明细及转账记录 6、修改密码 7、销户 8、退出等。
由于这是在Windows下开发的项目,其中涉及到Windows下的网络通信和线程的知识,所以首先我对此做了一些了解,相比于Linux下的网络编程,Windows下基于TCP的C/S架构,服务器端除了socket,bind,listen,accept这些操作外,
l使用Winsock API编制的网络应用程序中,在调用任何一个Winsock函数之前都必须检查协议栈安装情况。因此多出了了一个WSAStartup这个函数。
服务器端代码:
Winsock启动,创建socket,bind绑定协议族、端口号和IP地址,listen等待客户端连接
SOCKET ser_init()
{
int ret = 0;
WORD wVersionRequested;
WSADATA wsaData;
struct sockaddr_in server_addr = {0};
wVersionRequested = MAKEWORD( 2, 2 );
ret = WSAStartup(wVersionRequested, &wsaData);
if ( ret != 0 )
{
return -1;
}
if (wsaData.wVersion != wVersionRequested)
{
WSACleanup( );
return -1;
}
SOCKET sfd;
sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sfd == INVALID_SOCKET)
{
cout<<"1error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
cout<<"socket success..."<<endl;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(6666);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int opt = 1;
ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
if (ret == SOCKET_ERROR)
{
cout<<"2error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
ret = bind(sfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
if (ret == SOCKET_ERROR)
{
cout<<"3error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
cout<<"bind success..."<<endl;
ret = listen(sfd, 10);
if (ret == SOCKET_ERROR)
{
cout<<"4error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
cout<<"listen success..."<<endl;
return sfd;
}
accept接受客户端连接请求
SOCKET ser_acpt(SOCKET fd)
{
SOCKET cfd;
int len = sizeof(struct sockaddr);
struct sockaddr_in client_addr = {0};
cfd = accept(fd, (struct sockaddr*)&client_addr, &len);
if (cfd == INVALID_SOCKET)
{
cout<<"5error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
cout<<"accept success..."<<endl;
cout<<inet_ntoa(client_addr.sin_addr)<< "\t"<<ntohs(client_addr.sin_port)<<endl;
return cfd;
}
main函数
int main()
{
SOCKET fd,cfd;
fd = ser_init();
HANDLE hthread; //定义一个句柄,用来接收线程创建的返回值,成功返回true,失败返回false
DWORD tid; //创建的线程的ID号
while (1)
{
cfd = ser_acpt(fd);
hthread = CreateThread(NULL, 0, request, (LPVOID)cfd, 0, &tid);
if (false == hthread)
{
cout<<"create thread error"<<GetLastError<<endl;
}
WaitForSingleObject(hthread, 0);
CloseHandle(hthread);
}
closesocket(cfd);
WSACleanup();
return 0;
}
客户端同样也多出了启动Winsock的操作,相比于服务器,客户端在创建socket后,就立马进入到connect状态
客户端初始化:
SOCKET cli_init()
{
int ret = 0;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
ret = WSAStartup(wVersionRequested, &wsaData);
if ( ret != 0 )
{
return -1;
}
if (wsaData.wVersion != wVersionRequested)
{
WSACleanup();
return -1;
}
SOCKET cfd;
struct sockaddr_in server_addr = {0};
cfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (cfd == INVALID_SOCKET)
{
cout<<"1error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(6666);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(cfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1)
{
cout<<"2error with code = "<<WSAGetLastError()<<endl;
exit(1);
}
return cfd;
}
main函数:
int main()
{
int ret = 0;
SOCKET fd;
fd = cli_init();
WSACleanup();
}
服务器和客户端搭建好后,就到了客户端发请求给服务器,服务器处理请求,并返回处理结果给客户端。此次服务器端存储数据用了Mysql数据库,相比于在Linux下使用的小型数据库sqlite3, Mysql的功能非常强大,不但能实现多表查询,而且包含很多数据类型,查询语句丰富等等。这次就先到这里,后续会不断更新。