📄 serv.c
字号:
/**********************************************************************
*
* Toby Opferman
*
* Chat Server using Winsock
*
* This example is for educational purposes only. I license this source
* out for use in learning how to write a device driver.
*
* Copyright (c) 2005, All Rights Reserved
**********************************************************************/
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
/**********************************************************************
* Internal Data Structures
**********************************************************************/
typedef struct _client_info
{
SOCKET hSocket;
SOCKADDR_IN SockAddr;
char Nick[12];
BOOL bSetNick;
struct _client_info *Next;
} CLIENT_INFO, *PCLIENT_INFO;
typedef struct _server_info
{
SOCKET hServerSocket;
PCLIENT_INFO pClientInfoList;
fd_set stReadFDS, stXcptFDS;
int DataSockets;
BOOL bServerIsRunning;
} SERVER_INFO, *PSERVER_INFO;
typedef enum
{
SERV_WINSOCK_INIT_ERROR = 1,
SERV_WINSOCK_SOCKET_ERROR,
SERV_WINSOCK_BIND_ERROR,
SERV_WINSOCK_LISTEN_ERROR,
SERV_WINSOCK_LOCALIP_ERROR,
SERV_MEMORY_ERROR
} SERV_ERROR;
/**********************************************************************
* Internal Prototypes
**********************************************************************/
BOOL Serv_InitializeWinsock(void);
SOCKET Serv_CreateServer(void);
void Serv_RunServer(SOCKET hServerSocket);
void Serv_DisplayErrorMsg(SERV_ERROR uiMsg);
void Serv_FreeWinsock(void);
BOOL Serv_DisplayLocalIp(SOCKADDR_IN *SockAddr);
void Serv_ProcessIncommingSockets(PSERVER_INFO pServerInfo);
void Serv_ProcessChatBroadcast(PSERVER_INFO pServerInfo);
BOOL Serv_ProcessSocketWait(PSERVER_INFO pServerInfo);
void Serv_SendNewClientBroadCast(SOCKET hClientSocket, PSERVER_INFO pServerInfo);
PCLIENT_INFO Serv_CreateNewClient(SOCKET hNewClientSocket, SOCKADDR_IN *pNewClientSockAddr);
void Serv_SendClientBroadCast(PCLIENT_INFO pClientInfo, PSERVER_INFO pServerInfo, char *pszBuffer);
void Serv_FreeClientList(PSERVER_INFO pServerInfo);
/**********************************************************************
*
* main
*
* Console App Entry Function
*
**********************************************************************/
int __cdecl main(void)
{
if(Serv_InitializeWinsock())
{
SOCKET hServSocket;
hServSocket = Serv_CreateServer();
if(hServSocket != INVALID_SOCKET)
{
Serv_RunServer(hServSocket);
}
Serv_FreeWinsock();
}
return 0;
}
/**********************************************************************
*
* Serv_InitializeWinsock
*
* Initialize Winsock
*
**********************************************************************/
BOOL Serv_InitializeWinsock(void)
{
BOOL bInitialized = FALSE;
WSADATA WsaData;
if(WSAStartup(MAKEWORD(1, 1), &WsaData) != 0)
{
Serv_DisplayErrorMsg(SERV_WINSOCK_INIT_ERROR);
}
else
{
bInitialized = TRUE;
}
return bInitialized;
}
/**********************************************************************
*
* Serv_FreeWinsock
*
* Free Winsock
*
**********************************************************************/
void Serv_FreeWinsock(void)
{
WSACleanup();
}
/**********************************************************************
*
* Serv_DisplayErrorMsg
*
* Displays Error Messages
*
**********************************************************************/
void Serv_DisplayErrorMsg(SERV_ERROR uiMsg)
{
switch(uiMsg)
{
case SERV_WINSOCK_INIT_ERROR:
printf("Chat Server - Cannot Initialize Winsock!\n");
break;
case SERV_WINSOCK_SOCKET_ERROR:
printf("Chat Server - Cannot Create Socket!\n");
break;
case SERV_WINSOCK_BIND_ERROR:
printf("Chat Server - Cannot Bind Socket to Port!\n");
break;
case SERV_WINSOCK_LISTEN_ERROR:
printf("Chat Server - Cannot Listen on Port!\n");
break;
case SERV_WINSOCK_LOCALIP_ERROR:
printf("Chat Server - Cannot Find Local IP Address!\n");
break;
case SERV_MEMORY_ERROR:
printf("Chat Server - Out of Memory!\n");
break;
default:
printf("Chat Server - Runtime Error!\n");
}
}
/**********************************************************************
*
* Serv_CreateServer
*
* Creates the Listener
*
**********************************************************************/
SOCKET Serv_CreateServer(void)
{
SOCKET hSocket = INVALID_SOCKET;
SOCKADDR_IN SockAddr = {0};
UINT uiErrorStatus;
/*
* Create a socket
*/
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if(hSocket != INVALID_SOCKET)
{
SockAddr.sin_family = PF_INET;
SockAddr.sin_port = htons(4000);
/*
* BIND the Socket to a Port
*/
uiErrorStatus = bind(hSocket, (struct sockaddr *)&SockAddr, sizeof(SOCKADDR_IN));
if(uiErrorStatus != INVALID_SOCKET)
{
/*
* Start Listening
*/
if(listen(hSocket, 5) == 0)
{
/*
* Display Local IP Address
*/
if(Serv_DisplayLocalIp(&SockAddr) == FALSE)
{
Serv_DisplayErrorMsg(SERV_WINSOCK_LOCALIP_ERROR);
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
}
else
{
Serv_DisplayErrorMsg(SERV_WINSOCK_LISTEN_ERROR);
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
}
else
{
Serv_DisplayErrorMsg(SERV_WINSOCK_BIND_ERROR);
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
}
else
{
Serv_DisplayErrorMsg(SERV_WINSOCK_SOCKET_ERROR);
}
return hSocket;
}
/**********************************************************************
*
* Serv_DisplayLocalIp
*
* Displays a Local IP Address using a socket structure
*
**********************************************************************/
BOOL Serv_DisplayLocalIp(SOCKADDR_IN *SockAddr)
{
BOOL bDisplayedLocalIp = FALSE;
char HostName[101];
LPHOSTENT Host;
/*
* If the Local IP Address is not in the SOCKADDR data structure, then
* attempt to find it.
*/
if(!SockAddr->sin_addr.s_addr)
{
if(gethostname(HostName, 100) != SOCKET_ERROR)
{
Host = gethostbyname((LPSTR)HostName);
if(Host)
{
SockAddr->sin_addr.s_addr = *((long *)Host->h_addr);
}
if(SockAddr->sin_addr.s_addr)
{
printf("Server IP Address = %i.%i.%i.%i\n", SockAddr->sin_addr.s_addr&0xFF,
SockAddr->sin_addr.s_addr>>8 & 0xFF,
SockAddr->sin_addr.s_addr>>16 & 0xFF,
SockAddr->sin_addr.s_addr>>24 & 0xFF);
printf("Server Port Number = %i\n", htons(SockAddr->sin_port));
bDisplayedLocalIp = TRUE;
}
}
}
else
{
bDisplayedLocalIp = TRUE;
printf("Server IP Address = %i.%i.%i.%i\n", SockAddr->sin_addr.s_addr&0xFF,
SockAddr->sin_addr.s_addr>>8 & 0xFF,
SockAddr->sin_addr.s_addr>>16 & 0xFF,
SockAddr->sin_addr.s_addr>>24 & 0xFF);
printf("Server Port Number = %i\n", htons(SockAddr->sin_port));
}
return bDisplayedLocalIp;
}
/**********************************************************************
*
* Serv_RunServer
*
* Runs the server
*
**********************************************************************/
void Serv_RunServer(SOCKET hServerSocket)
{
SERVER_INFO ServerInfo = {0};
printf("Toby Opferman's Simple Chat Broadcast Server Example is Running\n");
printf("Type 'Q' to Quit\n");
ServerInfo.hServerSocket = hServerSocket;
ServerInfo.bServerIsRunning = TRUE;
while(ServerInfo.bServerIsRunning)
{
if(Serv_ProcessSocketWait(&ServerInfo))
{
Serv_ProcessIncommingSockets(&ServerInfo);
Serv_ProcessChatBroadcast(&ServerInfo);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -