C++实现socket网络通信CSock类的封装

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 运行结果

首先启动服务器端,如下:
在这里插入图片描述
再启动客户端(可同时启动多个),如下:
在这里插入图片描述
多个客户端可以向客户端同时发送消息
在这里插入图片描述
客户端按#退出
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值