[C++] Windows下的socket编程(这是一个简单的TCP/IP例子)

Socket的概念:

Socket,即套接字,用于描述地址和端口,是一个通信链的句柄。

应用程序通过Socket像网络发出请求或者回应。


什么事客户/服务器模式:

在TCP/IP网络应用中,通信的两个进程相互作用的主要模式是客户/服务器模式,即客户端向服务器发出请求,服务器接收请求后,提供相应的服务。客户/服务器模式的建立基于以下两点:

1:建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用

2:网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区

因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务端模式的TCP/IP

(这部分内容摘自socket编程原理)


需要做什么:

客户端:建立Socket,通过端口号和地址确定目标服务器,使用Connect连接到服务器,send发送消息,等待处理,通信完成后调用CloseSocket关闭Socket

服务端:建立Socket,声明自身的端口号和地址并绑定到Socket,使用Listen打开监听,然后不断用Accept去查看是否有连接,如果有,捕获Socket,并通过Recv获取消息的内容,通信完成后调用CloseSocket关闭这个对应Accept到的Socket,如果不再需要等待任何客户端连接,那么用CloseSocket关闭掉自身的Socket

 

代码示例

客户端:这里创建一个CLientNet类,用于表示一个客户

 

#pragma once

/*
ClinetNet.h:
用于表示一个客户的网络操作
*/

#include <stdio.h>
#include<windows.h>

#pragma comment(lib, "Ws2_32.lib")

class CClientNet
{
public:
	//连接上指定服务器
	int Connect(int port,const char* address);
	//发送信息
	int SendMsg(const char* msg,int len);
	//关闭
	void Close();

private:
	SOCKET m_sock;
};

 

/*
CLientNet.cpp
*/
#include "ClientNet.h"


int CClientNet::Connect( int port,const char* address )
{
	int rlt = 0;

	//用于记录错误信息并输出
	int iErrMsg;
	//启动WinSock
	WSAData wsaData;
	iErrMsg = WSAStartup(MAKEWORD(1,1),&wsaData);
	if (iErrMsg != NO_ERROR)
		//有错误
	{
		printf("failed with wsaStartup error : %d\n",iErrMsg);

		rlt = 1;
		return rlt;
	}

	//创建Socket
	m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (m_sock == INVALID_SOCKET)
		//创建Socket失败
	{
		printf("socket failed with error : %d\n",WSAGetLastError());

		rlt = 2;
		return rlt;
	}

	//目标服务器数据
	sockaddr_in sockaddrServer;
	sockaddrServer.sin_family = AF_INET;
	sockaddrServer.sin_port = port;
	sockaddrServer.sin_addr.s_addr = inet_addr(address);

	//连接,sock与目标服务器连接
	iErrMsg = connect(m_sock,(sockaddr*)&sockaddrServer,sizeof(sockaddrServer));
	if (iErrMsg < 0)
	{
		printf("connect failed with error : %d\n",iErrMsg);

		rlt = 3;
		return rlt;
	}

	return rlt;
}




int CClientNet::SendMsg(const char* msg,int len)
{
	int rlt = 0;

	int iErrMsg = 0;

	//发送消息,指定sock发送消息
	iErrMsg = send(m_sock,msg,len,0);
	if (iErrMsg < 0)
		//发送失败
	{
		printf("send msg failed with error : %d\n",iErrMsg);

		rlt = 1;
		return rlt;
	}

	return rlt;
}

void CClientNet::Close()
{
	closesocket(m_sock);
}

 

#include "ClientNet.h"

void main()
{
	CClientNet client;
	
	//连接到127.0.0.1(即本地),端口号为8888的服务端
	printf("Connect\n");
	client.Connect(8888,"127.0.0.1");
	
	//发送消息
	printf("send msg\n");
	client.SendMsg("hello\0",sizeof("hello\0"));
	
	//关闭socket
	printf("close\n");
	client.Close();

	system("pause");
}


 

服务端代码:

 

#pragma once

/*
ServerNet.h
用于表示服务端的网络操作

*/

#include <stdio.h>
#include <winsock.h>

#pragma comment (lib,"ws2_32.lib")

class CServerNet
{
public:

	//初始化服务器,返回0表示成功
	int Init(const char* address,int port);

	//更新数据
	void Run();


private:
	SOCKET m_sock;
};

 

/*
ServerNet.cpp
*/
#include "ServerNet.h"

int CServerNet::Init( const char* address,int port )
{
	int rlt = 0;

	//用于记录错误信息,并输出
	int iErrorMsg;

	//初始化WinSock
	WSAData wsaData;
	iErrorMsg = WSAStartup(MAKEWORD(1,1),&wsaData);
	
	if (iErrorMsg != NO_ERROR)
	{
		//初始化WinSock失败
		printf("wsastartup failed with error : %d\n",iErrorMsg);

		rlt = 1;
		return rlt;
	}

	//创建服务端Socket
	m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (m_sock == INVALID_SOCKET)
		
	{
		//创建Socket异常
		printf("socket failed with error : %d\n",WSAGetLastError());

		rlt = 2;
		return rlt;
	}

	//声明信息
	sockaddr_in serverAddr;
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = port;
	serverAddr.sin_addr.s_addr = inet_addr(address);

	//绑定
	iErrorMsg = bind(m_sock,(sockaddr*)&serverAddr,sizeof(serverAddr));
	if (iErrorMsg < 0)
	{
		//绑定失败
		printf("bind failed with error : %d\n",iErrorMsg);
		rlt = 3;
		return rlt;
	}

	

	return rlt;
}

void CServerNet::Run()
{
	//公开连接
	listen(m_sock,5);

	sockaddr_in tcpAddr;
	int len = sizeof(sockaddr);
	SOCKET newSocket;
	char buf[1024];
	int rval;

	do 
	{
		//接收信息
		newSocket = accept(m_sock,(sockaddr*)&tcpAddr,&len);

		
		if (newSocket == INVALID_SOCKET)
		{
			//非可用socket

		}
		else
		{
			//新socket连接
			printf("new socket connect : %d\n",newSocket);


			//消息处理
			do
			{
				printf("process\n");
				//接收数据
				memset(buf,0,sizeof(buf));
				rval = recv(newSocket,buf,1024,0);

				
				if (rval == SOCKET_ERROR)
					//这应该是个异常,当客户端没有调用closeSocket就直接退出游戏的时候,将会进入这里
					printf("recv socket error\n");

				
				
				if (rval == 0)
					//recv返回0表示正常退出
					printf("ending connection");
				else
					//显示接收到的数据
					printf("recv %s\n",buf);


			}while(rval != 0);

			//关闭对应Accept的socket
			closesocket(newSocket);
		}
		

		
	} while (1);

	//关闭自身的Socket
	closesocket(m_sock);
}


 

 

#include "ServerNet.h"

int main(int argc, char **argv)
{
	CServerNet serverNet;
	int iRlt = serverNet.Init("127.0.0.1",8888);
	if (iRlt == 0)
	{
		printf("init ok...\n");
		serverNet.Run();
	}
	else
		printf("serverNet init failed with error : %d\n",iRlt);
	system("pause");
}

 

 


#pragma once/*ClinetNet:用于表示一个客户的网络操作*/#include <stdio.h>#include<windows.h>#pragma comment(lib, "Ws2_32.lib")class CClientNet{public://连接上指定服务器int Connect(int port,const char* address);//发送信息int SendMsg(const char* msg,int len);//关闭void Close();private:SOCKET m_sock;};
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件、客户端组件和Agent组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/C++、C#、Delphi、E(易语言)、Java、Python 等编程语言接口。HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中。    为了让使用者能方便快速地学习和使用 HP-Socket ,迅速掌握框架的设计思想和使用方法,特此精心制作了大量 Demo 示例(如:PUSH 模型示例、PULL 模型示例、PACK 模型示例、性能测试示例以及其它编程语言示例)。HP-Socket 目前运行Windows 平台,将来会实现跨平台支持。 [15:47 2018/11/05] 同步更新到5.4.2正式版 [10:37 2018/10/23] 1、英文模块IHttpSyncClient组件大改 2、IWinHttp组件添加若干命令(PS:忘记是哪些了。。。) 3、升级到5.4.2 rc3 版本 4、增加client同步例子 [10:30 2018/9/25] v5.4.2 更新: > SSL 组件更新: ----------------- 1、SSL 组件可以手工启动 SSL 握手,从而可以对 SSL/Https 通信执行代理服务器设置等前置操作 2、SSL 组件(Server/Agent/Client)增加以下接口方法支持手工启动 SSL 握手 1) StartSSLHandShake():手工启动 SSL 握手,当通信组件设置为非自动握手时,需要调用本方法启动 SSL 握手 2) SetSSLAutoHandShake():设置通信组件握手方式(默认:TRUE,自动握手) 3) IsSSLAutoHandShake():获取通信组件握手方式 > 其他功能更新: ----------------- 1、所有可能导致 Socket 关闭的组件接口方法都在 Socket 通信线程中异步触发 OnClose 事件 2、Server 与 Agent 组件的 DIRECT 发送策略也支持通过 GetPendingDataLength() 方法实现流控 3、Server 与 Agent 组件的 Disconnect() 方法不再支持‘非强制断开’(仍然保留bForce 参数),调用时都会强制断开 4、OnSend 事件支持 三种同步策略 1) OSSP_NONE:不同步(默认) 1) OSSP_CLOSE:同步 OnClose 1) OSSP_RECEIVE:同步 OnClose 和 OnReceive(只用于 TCP 组件) > 升级说明: ----------------- 1、HP-Socket v5.4.2 完全兼容 HP-Socket v5.4.1 版本,可以直接替换升级 [18:41 2018/8/27] 1、修复英文模块submit_task最后一个参数错误问题,莫名其妙变成了字节集 [11:04 2018/8/27] 1、更新hpsocket为 beta11 2、submit_task 提交的任务不用去管回调里面的ptask参数。内部自动处理。 [16:57 2018/8/24] 1、修复中文模块部分命令错误问题 2、修复英文模块几处命令错误问题 3、增加websocket例程,本来httpclient里面人,有些人就是装看不见。 4、更新hpsocket为 beta9 [12:57 2018/8/15] 1、修复模块汇编的bug,原因是取消了ww汇编库 [11:55 2018/8/15] 1、模块更新为beta8 2、新增api: HP_Agent_IsConnected  -->  Agent.IsConnected() HP_Client_IsConnected  -->  Client.IsConnected() HP_Server_IsConnected  -->  Server.IsConnected() [9:18 2018/8/6] 1、性能优化 2、由于某些人吐槽中文版模块吐槽的厉害,遂决定不再更新中文版。 3、\demo\old 目录下放的是以前旧的例程源码,并不再更新 [12:57 2018/8/1] 修改模块IBufferPtr类,具体调用方式查看 TestEcho-New-Agent.e TestEcho-New-Server.e TestEcho-Http-Serve.e TestEcho-Http-Serve-bigfile.e  改名为 TestEcho-Ht

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值