📄 main.cpp
字号:
//-----------------------------------------------------------------------------
// Name: Sockets_TurnGame
//
// Description: Example code showing how to implement
// simple turn-based gameplay over TCP/IP
//
// File Function: Main program file (main.cpp)
//
// Code:
// Copyright (c) 2003 LostLogic Corporation. All rights reserved.
//
// Libraries Required:
// ws2_32.lib
// winmm.lib
//
// Local Files Required:
// main.h
// main.cpp
//
//-----------------------------------------------------------------------------
// Main header
#include "main.h"
//
// Function to Create the Window and Display it ( REQUIRED FOR ALL WINDOWS PROGRAMS )
//
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wndclass;
// Set up window attributes
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = fnMessageProcessor;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = lpszApplicationName; // Registered Class Name
wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
if( RegisterClassEx( &wndclass ) == 0 )
{
// Do error logic here
exit(1);
}
// Create the window
hWnd = CreateWindow( lpszApplicationName, // Application Name
lpszTitle, // Name Displayed on Title Bar
WS_OVERLAPPEDWINDOW,
100,
100,
400,
340,
NULL,
NULL,
hInstance,
NULL );
// Set global handles
g_hInst = hInstance;
g_hWnd = hWnd;
// Create child window controls
vCreateWindowControls( hWnd );
// Initialize sockets
vInitializeSockets();
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// Enter the message loop
while( msg.message != WM_QUIT ) {
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
};
// Clean up sockets
vShutdownSockets();
return(msg.wParam);
}
// -------------------------------------------------------------------------------
LRESULT CALLBACK fnMessageProcessor ( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
switch (iMsg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
// Check if player wants to connect to the server
case IDC_hBU_Connect:
vConnect();
break;
// Check if player wants to host the server
case IDC_hBU_Host:
vHost();
break;
// Signal that I am done taking my turn
case IDC_hBU_TurnDone:
PlaySound("button.wav",NULL,SND_FILENAME|SND_ASYNC);
if( g_bMyTurn ) {
vTurnDone();
}
break;
default:
break;
}
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
break;
}
return DefWindowProc( hWnd, iMsg, wParam, lParam );
}
//
// Function to Initialize window objects
//
void vCreateWindowControls(HWND hWnd)
{
// hEB_InputServerIP
hST_TextServerIP = CreateWindow(
"static","Server IP",
WS_CHILD | SS_CENTER | WS_VISIBLE,
5,
5,
120,
28,
hWnd,(HMENU)IDC_hST_TextServerIP,g_hInst,NULL);
// hEB_InputServerIP
hST_TextServerPort = CreateWindow(
"static","Port",
WS_CHILD | SS_CENTER | WS_VISIBLE,
125,
5,
50,
28,
hWnd,(HMENU)IDC_hST_TextServerPort,g_hInst,NULL);
// hEB_InputServerIP
hEB_InputServerIP = CreateWindowEx(
WS_EX_CLIENTEDGE,
"EDIT","192.168.0.2",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
5,
20,
120,
28,
hWnd,(HMENU)IDC_hEB_InputServerIP,g_hInst,NULL);
// hEB_InputServerPort
hEB_InputServerPort = CreateWindowEx(
WS_EX_CLIENTEDGE,
"EDIT","6001",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
125,
20,
50,
28,
hWnd,(HMENU)IDC_hEB_InputServerPort,g_hInst,NULL);
// hLB_Output
hLB_Output = CreateWindowEx(
WS_EX_CLIENTEDGE,
"LISTBOX",
NULL,
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | WS_BORDER,
5,
47,
380,
230,
hWnd,(HMENU)IDC_hLB_Output,g_hInst,NULL);
// hBU_Connect
hBU_Connect = CreateWindow(
"BUTTON",
"Connect",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
285,
280,
100,
28,
hWnd,(HMENU)IDC_hBU_Connect,g_hInst,NULL);
// hBU_Host
hBU_Host = CreateWindow(
"BUTTON",
"Host",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
175,
280,
100,
28,
hWnd,(HMENU)IDC_hBU_Host,g_hInst,NULL);
}
//
// Function to Initialize sockets
//
void vInitializeSockets( void )
{
WSADATA wsaData;
WORD wVersionRequested;
// Tell WinSock we want version 2
wVersionRequested = MAKEWORD( 2, 0 );
// Startup WinSock
WSAStartup( wVersionRequested, &wsaData );
}
//
// Function to display text into the edit window
//
void vShowText(char *szText)
{
int Line;
// add string to the listbox
SendMessage(hLB_Output,LB_ADDSTRING,0,(LPARAM) szText);
// determine number of items in listbox
Line = SendMessage(hLB_Output,LB_GETCOUNT,0,0);
// flag last item as the selected item, to scroll listbox down
SendMessage(hLB_Output,LB_SETCURSEL,Line-1,0);
// unflag all items to eliminate negative highlite
SendMessage(hLB_Output,LB_SETCURSEL,-1,0);
}
//
// Function to host the game. The host listens on a socket and
// accepts the client connection when it comes in. Once the client
// is connected, the server waits for the first game turn packet.
//
void vHost( void )
{
sockaddr_in saServerAddress;
sockaddr_in saClientAddress;
int iClientSize = sizeof(sockaddr_in);
int iPort = 6001;
int iStatus;
// ** FOR YOU TO DO **
// Pull the port number from the
// windows controls.
// Set global var
g_bIsServer = 1;
// Initialize the socket handle
g_skListenSocket = INVALID_SOCKET;
// Create the socket
g_skListenSocket = socket( AF_INET, SOCK_STREAM, 0 );
// Check if there was an error
if( g_skListenSocket == INVALID_SOCKET ) {
vShowText( "** ERROR ** Could Not Create Socket" );
return;
}
vShowText( "<- Socket Created ->" );
// Clear out the socket address structure
memset(&saServerAddress, 0, sizeof(sockaddr_in));
// Initialize the socket address structure
saServerAddress.sin_family = AF_INET;
saServerAddress.sin_addr.s_addr = htonl( INADDR_ANY );
saServerAddress.sin_port = htons( iPort );
// Attempt to bind
if( bind( g_skListenSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr) ) == SOCKET_ERROR ) {
vShowText( "** ERROR ** Could Not Bind Socket" );
return;
}
vShowText( "<- Socket Bound ->" );
// Listen for a connection
iStatus = listen( g_skListenSocket, 32 );
if( iStatus == SOCKET_ERROR ) {
vShowText( "** ERROR ** Could Not Listen" );
// Close the socket
closesocket(g_skListenSocket);
return;
}
vShowText( "<- Socket Listening ->" );
g_skClientSocket = accept( g_skListenSocket, (struct sockaddr*)&saClientAddress, &iClientSize );
if( g_skClientSocket == INVALID_SOCKET ) {
vShowText( "** ERROR ** Could Not Accept Client" );
// Close the socket
closesocket(g_skListenSocket);
return;
}
// Turn off buttons
DestroyWindow( hBU_Connect );
DestroyWindow( hBU_Host );
vShowText( "<- Client Connected ->" );
// Flag as connected
g_bConnected = 1;
// Flag that it is the other player's turn
// to end the turn
g_bMyTurn = 0;
// Wait for client's first turn
vTurnDone();
}
//
// Function to connect to the host game server. Once connected, the
// client has the option to end the turn.
//
void vConnect( void )
{
sockaddr_in saServerAddress;
int iPort = 6001,iStatus;
LPHOSTENT lpHost;
char szHost[128];
// ** FOR YOU TO DO **
// Pull the server IP and port number from the
// windows controls.
// Set global var
g_bIsServer = 0;
// Init the host value, change this IP to whatever valid IP you wish
sprintf( szHost,"192.168.0.2" );
// Initialize the socket handle
g_skClientSocket = INVALID_SOCKET;
// Create the socket
g_skClientSocket = socket( AF_INET, SOCK_STREAM, 0 );
// Check if there was an error
if( g_skClientSocket == INVALID_SOCKET ) {
vShowText( "** ERROR ** Could Not Create Socket" );
return;
}
vShowText( "<- Socket Created ->" );
// Initialize the server address data structure
memset(&saServerAddress,0,sizeof(sockaddr_in));
// Set this by default
saServerAddress.sin_family = AF_INET;
// Load the IP Address
saServerAddress.sin_addr.s_addr = inet_addr(szHost);
// If the host specified is not an IP Address we must look up the value
if( saServerAddress.sin_addr.s_addr == INADDR_NONE )
{
vShowText( "<- Looking Up Host ID ->" );
// Get the host name
lpHost = gethostbyname(szHost);
// Check if we got something back
if (lpHost != NULL) {
// Load the server address with the host information
saServerAddress.sin_addr.s_addr = ((LPIN_ADDR)lpHost->h_addr)->s_addr;
}
else {
vShowText( "** ERROR ** Could Not locate host" );
return;
}
}
// Set the Server Port
saServerAddress.sin_port = htons(iPort);
// Attempt to connect to the server
iStatus = connect( g_skClientSocket, (struct sockaddr*)&saServerAddress,sizeof(sockaddr));
// Check if there was an error
if( iStatus == SOCKET_ERROR ) {
vShowText( "** ERROR ** Could Not Connect To Server" );
return;
}
// Turn off buttons
DestroyWindow( hBU_Connect );
DestroyWindow( hBU_Host );
vShowText( "<- Connected To Server ->" );
// Flag as connected
g_bConnected = 1;
// Flag that it is my turn to end the turn
g_bMyTurn = 1;
// Turn on the Turn Done window
hBU_TurnDone = CreateWindow(
"BUTTON",
"Turn Done",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
5,
280,
100,
28,
g_hWnd,(HMENU)IDC_hBU_TurnDone,g_hInst,NULL);
vShowText( ":Server waiting, make your turn" );
}
//
// Function to close any outstanding sockets
//
void vShutdownSockets( void )
{
// Check if connected
if( g_bConnected ) {
// Check if server
if( g_bIsServer ) {
// Close listen socket
closesocket( g_skListenSocket );
}
// Close client socket
closesocket( g_skClientSocket );
}
// Clean up WinSock
WSACleanup();
}
//
// Function to tell the other player the turn is complete.
//
void vTurnDone( void )
{
// If connected, check to send or receive turn message
if( g_bConnected ) {
// My turn, send the message
if( g_bMyTurn ) {
// Disable turn button
DestroyWindow( hBU_TurnDone );
// Send turn over message
vSendTurnMessage();
if( g_bIsServer ) {
vShowText( ":Waiting for client's turn" );
}
else {
vShowText( ":Waiting for servers's turn" );
}
// Wait for receive message
vReceiveTurnMessage();
if( g_bIsServer ) {
vShowText( ":Client waiting, make your turn" );
}
else {
vShowText( ":Server waiting, make your turn" );
}
}
else {
if( g_bIsServer ) {
vShowText( ":Waiting for client's turn" );
}
else {
vShowText( ":Waiting for servers's turn" );
}
// Wait for receive message
vReceiveTurnMessage();
if( g_bIsServer ) {
vShowText( ":Client waiting, make your turn" );
}
else {
vShowText( ":Server waiting, make your turn" );
}
}
}
}
//
// Sends the actual turn-end packet.
//
void vSendTurnMessage( void )
{
char szTurnPacket[ 32 ];
int iBytes = 0;
// Create a "dummy" packet
sprintf( szTurnPacket, "turnpacket" );
// Send the packet
iBytes = send( g_skClientSocket, szTurnPacket, 32, 0 );
if( iBytes != SOCKET_ERROR ) {
}
else {
vShowText( "** ERROR ** Sending" );
return;
}
// Set to receive mode now
g_bMyTurn = 0;
}
//
// Waits for a turn-end packet.
//
void vReceiveTurnMessage( void )
{
char szTurnPacket[ 32 ];
int iBytes = 0;
iBytes = recv( g_skClientSocket, szTurnPacket, 32, 0 );
// Check return code
if( iBytes != SOCKET_ERROR ) {
}
else {
vShowText( "** ERROR ** Receiving" );
return;
}
// Set to send mode now
g_bMyTurn = 1;
// Turn on the Turn Done button
hBU_TurnDone = CreateWindow(
"BUTTON",
"Turn Done",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
5,
280,
100,
28,
g_hWnd,(HMENU)IDC_hBU_TurnDone,g_hInst,NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -