- 代码来源于 》》》》》》》》》》》》》》》》》》》》》 Windows Sockets网络开发VC++ 这本书
- 在stdafx.h 中添加 #pragma comment(lib,"ws2_32.lib")
服务器实现
// ServerCSgreeting.cpp : 客户端与服务器相互问候。
//
#include "stdafx.h"
#include "winsock2.h"
#include "funtiondec.h" //所需函数声明
#include "string.h"
#define MAX_NUM_BUF 20 //需要读入数据的大小
#define SERVER_DLL_REEOR 1 //调用Windows sockets DLL失败
#define SERVER_API_ERROR 2 //调用socket DLL失败
#define SERVERPORT 5555 // 服务器TCP端口
//#define INVALID_SOCKET (SOCKET)(~0)
//#define SOCKET_ERROR (-1)
char bufRecv[MAX_NUM_BUF]; //读缓冲区
char bufSend[MAX_NUM_BUF]; //写缓冲区
SOCKET sServer; //服务器监听套接字
SOCKET sClient; //接受客户端套接字
bool bConning; //与客户端的连接状态变量
/*
初始化成员变量
*/
void InitMember(void)
{
//初始化读和写缓冲区
memset(bufRecv, 0, MAX_NUM_BUF);
memset(bufSend, 0, MAX_NUM_BUF);
//初始化
sServer = INVALID_SOCKET;
sClient = INVALID_SOCKET;
//没有连接状态
bConning = FALSE;
}
/*
Windows Sockets 动态库的初始化
*/
int InitWinSoDll(void)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int retVal = WSAStartup(wVersionRequested, &wsaData);
if (0 != retVal)
{
printf("Can not find a usable Windows Sockets dll!");
return SERVER_DLL_REEOR;
}
//确保WinSock DLL 支持1.1
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
printf("Can not find a usable Windows Sockets dll!");
WSACleanup();
return SERVER_DLL_REEOR;
}
return 0;
}
/*
创建套接字
*/
int CreateSocket(void)
{
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
return HandleSocketError("Failed socket()!");
}
return 0;
}
/*
错误处理
*/
int HandleSocketError(char *str)
{
printf("%s", str);
WSACleanup();
return SERVER_API_ERROR;
}
/*
绑定套接字
*/
int BindSoc(void)
{
//服务器套接字地址
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(SERVERPORT);
addrServ.sin_addr.s_addr = INADDR_ANY;
//绑定套接字
int retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
closesocket(sServer); //关闭套接字
return HandleSocketError("Failed bind()!"); //错误处理
}
return 0;
}
/*
监听
*/
int ListenSoc(void)
{
//开始监听
int retVal = listen(sServer, 1);
if (SOCKET_ERROR == retVal)
{
closesocket(sServer);
return HandleSocketError("Failed listen()!");
}
//等待客户端的连接
printf("Server succeeded!\n");
printf("Waiting for new clients...\n");
return 0;
}
/*
接受请求
*/
int AcceptSoc(void)
{
//接受客户端请求
sockaddr_in addrClient;
int addrClientlen = sizeof(addrClient);
sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen);
if (INVALID_SOCKET == sClient)
{
closesocket(sServer);
return HandleSocketError("Failed accept()!");
}else
{
bConning = TRUE; //客户端请求成功
}
//显示客户端的IP和端口
char *pClientIP = inet_ntoa(addrClient.sin_addr);
u_short clientPort = ntohs(addrClient.sin_port);
printf("Accept a client.\n");
printf("IP:%s\n", pClientIP);
printf("Port:%d\n", clientPort);
return 0;
}
/*
接收数据
*/
BOOL RecvLine(SOCKET s, char* buf)
{
BOOL retVal = TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = 0; //读入字节数
int nDataLen = 0; //数据长度
while (!bLineEnd && bConning) //与客户端连接 没有换行
{
nReadLen = recv(s, buf + nDataLen, 1, 0); // 每次接收一个字节
//错误处理
if (SOCKET_ERROR == nReadLen)
{
int nErrCode = WSAGetLastError(); //错误代码
if (WSAENOTCONN == nErrCode)
{
printf("The socket is not conected!\n");
}
else if (WSAESHUTDOWN == nErrCode)
{
printf("The socket has been shut down!\n");
}
else if (WSAETIMEDOUT == nErrCode)
{
printf("The connection has been dropped!\n");
}
else if (WSAECONNRESET == nErrCode)
{
printf("The virtual circuit was reset by the remote side!\n");
}
else{}
retVal = FALSE;// 读取数据失败
break;
}
if (0 == nReadLen) //客户端关闭
{
retVal = FALSE; //读取数据失败
break;
}
//读入数据
if ('\n' == *(buf + nDataLen))
{
bLineEnd = TRUE; //接收数据结束
}
else
{
nDataLen += nReadLen; //增加数据掺毒
}
}
return retVal;
}
/*
发送一行数据
*/
BOOL SendLine(SOCKET s, char* str)
{
int retVal; //返回值
retVal = send(s, str, strlen(str), 0); //一次发送
//错误处理
if (SOCKET_ERROR == retVal)
{
int nErrCode = WSAGetLastError();
if (WSAENOTCONN == nErrCode)
{
printf("The socket is not conected!");
}
else if (WSAESHUTDOWN == nErrCode)
{
printf("The socket has been shut down!");
}
else if (WSAETIMEDOUT == nErrCode)
{
printf("The connection has been dropped!");
}
else{}
return FALSE; //发送失败
}
return TRUE; //发送成功
}
/*
退出
*/
int ExitClient(int nExit)
{
closesocket(sServer); //关闭监听套接字
closesocket(sClient); //关闭连接客户端套接字
WSACleanup(); //卸载Windows Sockets DLL清理内存
return nExit; //退出
}
int _tmain(int argc, _TCHAR* argv[])
{
char bufSend[MAX_NUM_BUF] = { NULL };
char bufRecv[MAX_NUM_BUF] = { NULL };
strcpy_s(bufSend, "Hello,Client!\n");
InitMember(); // 初始化成员
InitWinSoDll(); //初始化Windows Sockets DLL
CreateSocket(); //创建套接字
BindSoc(); //绑定套接字
ListenSoc(); //监听
AcceptSoc(); //接受客户端请求
if (!RecvLine(sClient, bufRecv)) //接收数据
{
return HandleSocketError("RecvLine Error!\n");
}
printf("RecvLine=%s\n", bufRecv);
printf("RecvLine succeeded!\n");
if (!SendLine(sClient, bufSend))//发送一行数据
{
return ExitClient(SERVER_API_ERROR);
}
ExitClient(0);
return 0;
}
客户端实现
// ClientCSgreeting.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "winsock2.h"
#include "funtiondec.h"
#include "string.h"
#define MAX_NUM_BUF 25 //需要读写入数据的大小
#define CLIENT_SOCKET_DLL_ERROR 1 //调用Windows sockets DLL失败
#define CLIENT_API_ERROR 2 //创建套接字失败
#define SERVERPORT 5555 // 服务器TCP端口
char bufRecv[MAX_NUM_BUF]; //读缓冲区
char bufSend[MAX_NUM_BUF]; //写缓冲区
SOCKET sHost; //套接字
bool bConning; //与服务器的连接状态变量
/*
初始化成员变量
*/
void InitMember(void)
{
//初始化读和写缓冲区
memset(bufRecv, 0, MAX_NUM_BUF);
memset(bufSend, 0, MAX_NUM_BUF);
//初始化
sHost = INVALID_SOCKET;
//没有连接状态
bConning = FALSE;
}
/*
Windows Sockets 动态库的初始化
*/
int InitWinSoDll(void)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
int err = WSAStartup(wVersionRequested, (LPWSADATA)&wsaData);
if (0 != err)
{
printf("Can not find a usable Windows Sockets dll!");
return CLIENT_SOCKET_DLL_ERROR;
}
return 0;
}
/*
创建套接字
*/
int CreateSocket(void)
{
//创建Windows socket
sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sHost)
{
ShowErrorMsg(); //显示错误信息
WSACleanup(); //释放资源
return CLIENT_API_ERROR; //退出
}
return 0;
}
/*
显示错误信息
*/
void ShowErrorMsg(void)
{
int nErrCode = WSAGetLastError(); //获取错误代码
HLOCAL hlocal = NULL;
//获取错误的文本字符串
BOOL fok = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, nErrCode, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(PTSTR)&hlocal, 0, NULL
);
//显示错误信息
if (hlocal != NULL)
{
MessageBox(NULL, (LPCWSTR)LocalLock(hlocal), _T("CLIENT ERROR"), MB_OK);
LocalFree(hlocal);
}
}
/*
客户端连接服务器
*/
int ConnectSoc(void)
{
//获取主机的信息
int retVal;
LPHOSTENT hostEntry;
char hostname[MAX_NUM_BUF];
gethostname(hostname, MAX_NUM_BUF); //获取主机名称
hostEntry = gethostbyname(hostname); //获取主机信息
if (!hostEntry)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
//设置sockaddr_in
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
addrServ.sin_port = htons(SERVERPORT);
char *pClientIP = inet_ntoa(addrServ.sin_addr);
printf("IP:%s\n", pClientIP);
//连接服务器
retVal = connect(sHost, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
else
{
bConning = TRUE; //连接服务器成功
printf("Connect succeedend!\n");
}
return 0;
}
/*
发送数据
*/
int SendData(char *str)
{
int retVal = send(sHost, str, strlen(str), 0);
if (SOCKET_ERROR == retVal)
{
ShowErrorMsg(); //显示错误信息
return ExitClient(CLIENT_API_ERROR); //退出
}
return 0;
}
/*
读取一行数据
*/
BOOL RecvLine(SOCKET s, char* buf)
{
BOOL retVal = TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = 0; //读入字节数
int nDataLen = 0; //数据长度
while (!bLineEnd && bConning)
{
nReadLen = recv(s, buf + nDataLen, 1, 0); //每次接收一个字节
//错误处理
if (SOCKET_ERROR == nReadLen)
{
retVal = FALSE; //读数据失败
break; // 跳出循环
}
if (0 == nReadLen) //客户端关闭
{
retVal = FALSE; //读数据失败
break;
}
//读入数据
if ('\n' == *(buf + nDataLen)) //换行符
{
bLineEnd = TRUE; //接收数据结束
}
else
{
nDataLen += nReadLen; //增加数据长度
}
}
return retVal;
}
/*
退出
*/
int ExitClient(int nExit)
{
closesocket(sHost); //关闭连接服务器套接字
WSACleanup(); //卸载Windows Sockets DLL清理内存
return nExit; //退出
}
int _tmain(int argc, _TCHAR* argv[])
{
char recvbuf[MAX_NUM_BUF] = { NULL };
char bufSend[MAX_NUM_BUF] = { NULL };
strcpy_s(bufSend, "Hello,Server!\n");
InitMember(); // 初始化成员
InitWinSoDll(); //初始化Windows Sockets DLL
CreateSocket(); //创建套接字
ConnectSoc(); //客户端连接套接字
if (SendData(bufSend) > 0) //向服务器发送数据
{
printf("ClientSend Error\n");
ExitClient(1);
}
else
{
printf("ClientSend succeeded\n");
}
if (RecvLine(sHost, recvbuf)) //读取一行数据
{
printf("ClientRecvLine=%s\n", recvbuf);
printf("RecvLine succeeded!\n");
}
ExitClient(1);
return 0;
}
效果图