[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;};

 

你可能感兴趣的:(socket编程)