zoukankan      html  css  js  c++  java
  • [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;};

  • 相关阅读:
    python 执行sql得到字典格式数据
    python爬虫 url链接编码成gbk2312格式
    windows环境下elasticsearch安装教程(单节点)
    python SQLServer 存储图片
    爬虫的本质是和分布式爬虫的关系
    requests form data 请求 爬虫
    mysql 删除 binlog 日志文件
    查看mysql数据表的大小
    xshell 连接报错 Disconnected from remote host
    centos 7.3 安装 mysqldb 报错 EnvironmentError: mysql_config not found ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3091388.html
Copyright © 2011-2022 走看看