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

  • 相关阅读:
    WEB新手之sql注入
    WEB新手之do u know caidao?
    C#发送邮件三种方法,Localhost,SMTP,SSL-SMTP
    利用SMTP发送Mail详解
    DevExpress GridControl List绑定方式下新增行的方法
    技术收藏书签
    Oracle CONNECT BY 用法
    在 Oracle Database 11g 第 2 版中查询层次结构数据的快速入门
    Jquery选择器(转载)
    MVC 验证
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3091388.html
Copyright © 2020-2023  润新知