现在的位置: 首页 > 综合 > 正文

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

2012年02月17日 ⁄ 综合 ⁄ 共 4358字 ⁄ 字号 评论关闭

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

 

抱歉!评论已关闭.