#include <winsock2.h>
#include <windows.h>
#include <string>
#include <time.h>
#pragma comment(lib, "WS2_32.lib")
using namespace std;
enum {FAILED_SOCKET = 5, FAILED_CONNECT, SUCCESS_SOCKET};
SOCKET s; /* 客户端使用的套接字 */
string serverIP = "127.0.0.1"; /* 服务器IP */
int serverPort = 6688; /* 端口号 */
HANDLE hThread = NULL;
DWORD dwThreadId = 0;
/* 与socket有关的所有准备工作都在这里完成 */
int CreateSocket(SOCKET &s, const string &serverIP, int port);
/* 销毁套接字,回收资源 */
int DestorySocket(SOCKET &s);
/* 在DC上显示响应结果 */
int PrintRespond(HWND hwnd, int x,
const string &str1, const string &str2, const string &str3);
/* 获取当前系统时间 */
string GetCurTime();
/* 接收数据线程,在这个线程中处理从服务器收到的数据 */
DWORD WINAPI RecvProc(LPVOID lp);
/* 窗口过程函数 */
LRESULT CALLBACK WinSunProc(HWND hwnd,
UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.hCursor = LoadCursor(NULL, NULL);
wndcls.hIcon = LoadIcon(NULL, NULL);
wndcls.hInstance = hInstance;
wndcls.lpfnWndProc = WinSunProc;
wndcls.lpszClassName = "xs";
wndcls.lpszMenuName = NULL;
wndcls.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls);
HWND hwnd = NULL;
hwnd = ::CreateWindow("xs", "客户端-方向键测试", WS_DLGFRAME | WS_SYSMENU,
0, 0, 400, 250, NULL, NULL, hInstance, NULL);
/* 服务器为本机127.0.0.1 开端口6688 */
int nRet = CreateSocket(s, serverIP, serverPort);
if(FAILED_SOCKET == nRet){
::MessageBox(hwnd, "socket()函数错误!请重新运行", "错误!", MB_OK);
::SendMessage(hwnd, WM_CLOSE, 0, 0);
}else if(FAILED_CONNECT == nRet){
::MessageBox(hwnd, "connect()函数错误!请重新运行", "错误!", MB_OK);
::SendMessage(hwnd, WM_CLOSE, 0, 0);
}
ShowWindow(hwnd, SW_SHOWNORMAL); /* 显示窗口 */
UpdateWindow(hwnd); /* 更新窗口 */
/* 启动线程开始接收数据 */
hThread = CreateThread(NULL, NULL, RecvProc, (LPVOID)(&hwnd), 0, &dwThreadId);
if(NULL == hThread){
DestorySocket(s);
::MessageBox(hwnd, "CreateThread函数错误!请重新运行", "错误!", MB_OK);
::SendMessage(hwnd, WM_CLOSE, 0, 0);
}
/* 消息循环 */
MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinSunProc(HWND hwnd,
UINT uMsg, WPARAM wParam, LPARAM lParam)
{
string str;
HDC hDC = NULL;
PAINTSTRUCT ps;
switch(uMsg)
{
case WM_KEYDOWN:
if(VK_UP == wParam){
::send(s, "1", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "上键按下", GetCurTime());
}else if(VK_LEFT == wParam){
::send(s, "3", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "左键按下", GetCurTime());
}else if(VK_RIGHT == wParam){
::send(s, "5", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "右键按下", GetCurTime());
}else if(VK_DOWN == wParam){
::send(s, "7", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "下键按下", GetCurTime());
}
break;
case WM_KEYUP:
if(VK_UP == wParam){
::send(s, "2", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "上键弹起", GetCurTime());
}else if(VK_LEFT == wParam){
::send(s, "4", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "左键弹起", GetCurTime());
}else if(VK_RIGHT == wParam){
::send(s, "6", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "右键弹起", GetCurTime());
}else if(VK_DOWN == wParam){
::send(s, "8", 2, 0);
PrintRespond(hwnd, 50, "本机响应", "下键弹起", GetCurTime());
}
break;
case WM_PAINT:
hDC = ::BeginPaint(hwnd, &ps);
str = "__________________________________________________";
::TextOut(hDC, 0, 0, str.c_str(), str.length());
str = " 已 成 功 连 接 到 服 务 器 ";
str += serverIP;
::TextOut(hDC, 0, 30, str.c_str(), str.length());
str = " 请 按 方 向 键 测 试";
::TextOut(hDC, 0, 55, str.c_str(), str.length());
str = "__________________________________________________";
::TextOut(hDC, 0, 75, str.c_str(), str.length());
::Rectangle(hDC, 190, 90, 191, 250);
EndPaint(hwnd,&ps);
break;
case WM_CLOSE:
::send(s, "CLOSE", strlen("CLOSE"), 0);
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
int CreateSocket(SOCKET &s, const string &serverIP, int port)
{
/* 初始化WS2_32.dll */
WSADATA wsaData;
WORD sockVer = MAKEWORD(2, 0);
::WSAStartup(sockVer, &wsaData);
/* 创建套接字 */
s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == s){
::WSACleanup();
return FAILED_SOCKET;
}
/* 填充sockaddr_in结构 */
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
/* 服务器IP */
serverAddr.sin_addr.S_un.S_addr = inet_addr(serverIP.c_str());
if(-1 == ::connect(s, (sockaddr*)&serverAddr, sizeof(serverAddr))){
::WSACleanup();
return FAILED_CONNECT;
}
return SUCCESS_SOCKET;
}
int DestorySocket(SOCKET &s)
{
::closesocket(s);
::WSACleanup(); /* 释放WS2_32库 */
return 0;
}
DWORD WINAPI RecvProc(LPVOID lp)
{
HWND hwnd = *((HWND*)lp);
HDC hDC = ::GetDC(hwnd);
char buff[256]; /* 接收数据缓冲区 */
int flag = 0;
while(1){
int nRecv = ::recv(s, buff, 256, 0);
if(nRecv > 0){
buff[nRecv] = '\0';
}
::TextOut(hDC, 250, 100, "服务器响应", strlen("服务器响应"));
if(0 == flag){
::TextOut(hDC, 220, 150, buff, strlen(buff));
flag = 1;
}else{
::TextOut(hDC, 220, 170, buff, strlen(buff));
flag = 0;
}
}
return 0;
}
string GetCurTime()
{
time_t t = time(0);
char tmp[64];
strftime(tmp, sizeof(tmp), "%X", localtime(&t));
return tmp;
}
int PrintRespond(HWND hwnd, int x,
const string &str1, const string &str2, const string &str3)
{
HDC hDC = ::GetDC(hwnd);
::TextOut(hDC, x, 100, str1.c_str(), str1.length());
::TextOut(hDC, x - 30, 150, str3.c_str(), str3.length());
::TextOut(hDC, x + 35, 150, str2.c_str(), str2.length());
return 0;
}