1.头文件
//SockLi.h
#pragma once
#include <WinSock2.h>
class CSockLi
{
protected:
SOCKET m_hSocket;
public:
BOOL GetPeerName(char* rSocketAddress, UINT& rSocketPort);
BOOL GetSockName(char* rSocketAddress, UINT& rSocketPort);
BOOL Create(UINT nSocketPort = 0, int nSockType = SOCK_STREAM,
LPCTSTR lpszSocketAddress=NULL);
BOOL Accept(CSockLi& rConnectedSock, LPSTR szIp = NULL, UINT *nPort = NULL);
BOOL Connection(LPCSTR lpszHostAddress, UINT nPort);
BOOL Listen(int nConnectionBacklog = 5)
{
return !listen(m_hSocket, nConnectionBacklog);
}
int Send(const void* lpBuf, int nBufLen, int nFlags = 0)
{
return send(m_hSocket, (LPCSTR)lpBuf, nBufLen, nFlags);
}
int SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCSTR lpszHostAddress = NULL,
int nFlags = 0);
int Receive(void* lpBuf, int nBufLen, int nFlags = 0)
{
return recv(m_hSocket, (LPTSTR)lpBuf, nBufLen, nFlags);
}
int ReceiveFrom(void* lpBuf, int nBufLen, char* rSocketAddress, UINT& rSocketPort, int nFlags = 0);
void Close()
{
closesocket(m_hSocket);
m_hSocket = INVALID_SOCKET;
}
CSockLi();
virtual ~CSockLi();
};
2.源文件
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include "SockLi.h"
#pragma comment(lib, "ws2_32.lib")
CSockLi::CSockLi()
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
m_hSocket = INVALID_SOCKET;
}
CSockLi::~CSockLi()
{
Close();
}
BOOL CSockLi::Create(UINT nSocketPort, int nSockType, LPCTSTR lpszSocketAddress)
{
m_hSocket = socket(AF_INET, nSockType, 0);//创建套接字
if (m_hSocket == INVALID_SOCKET)
return false;
//设置IP地址和端口
sockaddr_in sa = {AF_INET};
sa.sin_port = htons(nSocketPort);
if (lpszSocketAddress)
sa.sin_addr.s_addr = inet_addr(lpszSocketAddress);
//绑定套接字和IP地址端口
return !bind(m_hSocket, (sockaddr*)&sa, sizeof(sa));
}
int CSockLi::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCSTR lpszHostAddress,
int nFlags)
{
sockaddr_in to = {AF_INET};
to.sin_port = htons(nHostPort);
to.sin_addr.s_addr = inet_addr(lpszHostAddress);
return sendto(m_hSocket, (LPCSTR)lpBuf, nBufLen, nFlags, (sockaddr*)&to, sizeof(to));
}
int CSockLi::ReceiveFrom(void* lpBuf, int nBufLen, char* rSocketAddress, UINT& rSocketPort, int nFlags)
{
sockaddr_in from = {AF_INET};
int lenFrom=sizeof(from);
int n = recvfrom(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags, (sockaddr*)&from, &lenFrom);
strcpy(rSocketAddress, inet_ntoa(from.sin_addr));
rSocketPort = htons(from.sin_port);
return n;
}
BOOL CSockLi::GetPeerName(char* rSocketAddress, UINT& rSocketPort)
{
sockaddr_in name = { AF_INET };
int lenname = sizeof(name);
if (getpeername(m_hSocket, (sockaddr*)&name, &lenname) < 0)
return false;
strcpy(rSocketAddress, inet_ntoa(name.sin_addr));
rSocketPort = htons(name.sin_port);
return true;
}
BOOL CSockLi::GetSockName(char* rSocketAddress, UINT& rSocketPort)
{
sockaddr_in name = { AF_INET };
int lenname = sizeof(name);
if (getsockname(m_hSocket, (sockaddr*)&name, &lenname) < 0)
return false;
strcpy(rSocketAddress, inet_ntoa(name.sin_addr));
rSocketPort = htons(name.sin_port);
return true;
}
BOOL CSockLi::Accept(CSockLi& rConnectedSock, LPSTR szIp, UINT *nPort)
{
sockaddr_in sa = {AF_INET};
int nLen = sizeof(sa);
rConnectedSock.m_hSocket = accept(this->m_hSocket, (sockaddr*)&sa, &nLen);
if (rConnectedSock.m_hSocket == INVALID_SOCKET)
return false;
if(szIp)
strcpy(szIp, inet_ntoa(sa.sin_addr));
if(nPort)
*nPort = htons(sa.sin_port);
return true;
}
BOOL CSockLi::Connection(LPCSTR lpszHostAddress, UINT nPort)
{
sockaddr_in sa = { AF_INET };
sa.sin_port = htons(nPort);
sa.sin_addr.s_addr = inet_addr(lpszHostAddress);
return !connect(m_hSocket, (sockaddr*)&sa, sizeof(sa));
}
3.代码测试
3.1 Server.cpp
#include <iostream>
#include <process.h>
#include "SockLi.h"
using namespace std;
void ClientPro(void* p)
{
const char* p1 = "Welcome to connect";
CSockLi* pSock = (CSockLi*)p;
CSockLi socka = *pSock;
socka.Send(p1, strlen(p1));
//获取客户端信息
char sIp[20];
UINT nPort;
socka.GetPeerName(sIp, nPort);
char str[2048];
while (true)
{
int n = socka.Receive(str, sizeof(str));
if (n <= 0)
{
cout << sIp << "-" << nPort << "断开连接!" << endl;
break;
}
str[n] = 0;
cout << sIp << "-" << nPort << "说: ";
cout << str << endl;
}
}
int main()
{
//创建套接字
CSockLi sock;
//端口8233 IP地址设为127.0.0.1(本机IP)
if (!sock.Create(8233, SOCK_STREAM, "127.0.0.1"))
{
cout << "创建失败:" << GetLastError() << endl;
return -1;
}
//获取本机信息
char sSevIp[20];
UINT nSevPort;
sock.GetSockName(sSevIp, nSevPort);
puts("******************************************************");
cout << "IP:" << sSevIp << "\t" << "PORT:" << nSevPort << "\t服务器启动成功!" << endl;
puts("------------------------------------------------------");
//监听
sock.Listen(5);
//获取客户端信息
char sIp[20];//客户端IP地址
UINT nPort;//客户端端口
CSockLi socka;//客户端套接字对象
while (true)
{
sock.Accept(socka, sIp, &nPort);
cout << sIp << "-" << nPort << "登录了!" << endl;
//多线程,可同时处理多个客户端的连接
_beginthread(ClientPro, 0, &socka);
}
return 0;
}
3.2 Client.cpp
#include <iostream>
#include "SockLi.h"
using namespace std;
int main()
{
CSockLi sock;
if (!sock.Create(0, SOCK_STREAM))
{
cout << "创建失败:" << GetLastError() << endl;
return -1;
}
//获取本机信息
char sClientIp[20];
UINT nClientPort;
sock.GetSockName(sClientIp, nClientPort);
puts("******************************************************");
cout << "IP:" << sClientIp << "\t" << "PORT:" << nClientPort << "\t客户端启动成功!" << endl;
puts("------------------------------------------------------");
//连接服务器 IP:127.0.0.1 端口:8233
if (!sock.Connection("127.0.0.1", 8233))
{
cout << "连接服务器失败!" << GetLastError() << endl;
return -1;
}
char str[2048];
int n = sock.Receive(str, sizeof(str));
str[n] = 0;
cout << str << endl;
while (true)
{
cout << "请输入要发送的信息【按#退出】:" << endl;
cin >> str;
if (str[0] == '#')
break;
sock.Send(str, strlen(str));
}
sock.Close();
return 0;
}
3.3 运行结果
首先启动服务器端,如下:
再启动客户端(可同时启动多个),如下:
多个客户端可以向客户端同时发送消息
客户端按#退出