zoukankan      html  css  js  c++  java
  • Winsock网络编程

    Winsock是Windows下网络编程的标准接口。使用Winsock编程的步骤一般是比较固定的。

    首先要包含头文件#include <WinSock2.h>,同时要添加WS2_32.lib的链接:

    #include <WinSock2.h>
    
    #pragma comment(lib,"WS2_32") 
    

    每个 Winsock 应用程序必须加载相应版本的 Winsock DLL,一般通过WSAStartup函数实现,这个函数有两个功能,一是加载套接字库,二是进行套接字库的版本协商,也就是确定要使用的winsock版本。
    函数原型如下:

    int WSAAPI WSAStartup( __in WORD wVersionRequested,__out LPWSADATA lpWSAData );
    

    每一个对 WSAStartup 的调用必须对应一个对 WSACleanup 的调用,这个函数释放
    Winsock 库。

    int WSAAPI WSACleanup( void );  
    

    下面通过一些简单的例子来说明winsock编程的流程:

    基于TCP(面向连接)的socket编程

    基于TCP的socket编程服务端程序流程如下:

    • 创建套接字(socket)
    • 绑定套接字到指定的IP和端口号(bind)
    • 设置套接字进入监听状态(listen)
    • 等待客户连接请求(accept)
    • 收发数据,进行通信(send/recv)
    • 关闭套接字

    基于TCP的socket编程客户端程序流程如下:

    • 创建套接字(socket)
    • 向服务器发出连接请求(connect)
    • 和服务端进行通信(send/recv)
    • 关闭套接字

    //基于TCP的服务端程序

    #include <WinSock2.h>
    #include <iostream>
    #include <string>
    #pragma comment(lib,"WS2_32")
    
    using std::cout;
    using std::endl;
    using std::string;
    
    //服务器端程序
    void TcpServer()
    {
    	//加载winsock库
    	WSADATA wsaData;
    	WORD socktVersion = MAKEWORD(2,2);	//版本号
    	if (0 != ::WSAStartup(socktVersion,&wsaData))  //加载套接字库
    	{
    		return;
    	}
    
    	//1、创建服务器端套接字
    	SOCKET serverSocket = ::socket(AF_INET,SOCK_STREAM,0); //使用TCP连接
    
    	//2、绑定套接字到指定IP和端口
    	sockaddr_in server_address;
    	server_address.sin_family = AF_INET;
    	server_address.sin_port = htons(6000);	//指定端口号
    	server_address.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //指定IP地址
    	::bind(serverSocket,(LPSOCKADDR)&server_address,sizeof(server_address)); //绑定IP地址与端口号
    
    	//3、设置套接字为监听状态
    	::listen(serverSocket,5);//
    
    	char sendmsg[] = "TCP Server Say Hello!";
    	//4、等待客户端连接
    	cout << "
    Wait For Connect...";
    	while (true)
    	{
    		SOCKET client_socket;
    		sockaddr_in client_address;
    		int address_len = sizeof(client_address);
    		client_socket = ::accept(serverSocket,(LPSOCKADDR)&client_address,&address_len); //等待连接
    		if (client_socket == INVALID_SOCKET)
    		{
    			cout << "
    Failed Accept!";
    			break;
    		}
    		char *str_adress = inet_ntoa(client_address.sin_addr);
    		cout << "
    A client connected.   IP:" << str_adress;
    
    		//5、收发数据
    		::send(client_socket,sendmsg,strlen(sendmsg),0);
    
    		::closesocket(client_socket);//关闭连接
    	}
    
    
    	//6、关闭服务端socket
    	::closesocket(serverSocket);
    	::WSACleanup();	//释放winsock库
    }
    

    客户端程序:

    #include <WinSock2.h>
    #include <iostream>
    #include <string>
    
    #pragma comment(lib,"WS2_32")
    
    using std::cout;
    using std::endl;
    using std::string;
    
    
    void TCPClient()
    {
    	//加载winsock库
    	WSADATA wsaData;
    	WORD socktVersion = MAKEWORD(2,2);	//版本号
    	if (0 != ::WSAStartup(socktVersion,&wsaData))  //加载套接字库
    	{
    		return;
    	}
    
    	//1.建立socket
    	SOCKET clientSocket = ::socket(AF_INET,SOCK_STREAM,0); //使用TCP连接
    	//填写服务器地址
    	sockaddr_in server_address;
    	server_address.sin_family = AF_INET;
    	server_address.sin_port = htons(6000);	//连接端口号
    	server_address.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //服务器IP地址
    
    	//2、发出连接请求
    	if (-1 == ::connect(clientSocket,(LPSOCKADDR)&server_address,sizeof(server_address)))
    	{
    		cout << "
    Connect Server Failed!";
    		return;
    	}
    
    	cout << "
    Connected to server...";
    	//3、收发数据
    	char rev_buf[1024] = {0};
    	::recv(clientSocket,rev_buf,1024,0);
    	cout << "
    Receive server msg: " << rev_buf;
    	//4、关闭连接
    	::closesocket(clientSocket);
    	::WSACleanup();	//释放winsock库
    }
    

    运行如下:
    tcp_png

    基于UDP(面向无连接)的socket编程

    服务端程序流程如下:

    • 创建套接字(socket)
    • 绑定套接字到指定的IP和端口号(bind)
    • 等待接收数据(recvfrom)
    • 关闭套接字

    客户端程序流程如下:

    • 创建套接字(socket)
    • 向服务端发送数据(sendto)
    • 关闭套接字

    基于UDP的服务端程序,接收客户端发送的数据,并输出

    void UdpServer()
    {
    	//加载winsock库
    	WSADATA wsaData;
    	WORD socktVersion = MAKEWORD(2,2);	//版本号
    	if (0 != ::WSAStartup(socktVersion,&wsaData))  //加载套接字库
    	{
    		return ;
    	}
    
    	//1.建立socket
    	SOCKET serverSocket = ::socket(AF_INET,SOCK_DGRAM,0); //使用UDP协议
    	//填写地址
    	sockaddr_in server_address;
    	server_address.sin_family = AF_INET;
    	server_address.sin_port = htons(6000);	//连接端口号
    	server_address.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //服务器IP地址
    
    	//2、绑定套接字
    	::bind(serverSocket,(LPSOCKADDR)&server_address,sizeof(server_address)); //绑定IP地址与端口号
    
    	//3、接收数据
    	char recv_buf[1024] = {0};
    	sockaddr_in client_address;
    	int address_len = sizeof(client_address);
    	while (true)
    	{
    		//接收数据
    		int recv_cnt = ::recvfrom(serverSocket,recv_buf,1024,0,(sockaddr*)&client_address,&address_len);
    		if (recv_cnt > 0)
    		{
    			recv_buf[recv_cnt] = '';
    			cout << "
    Receive Data From " << inet_ntoa(client_address.sin_addr) << " : " << recv_buf;
    		}
    	}
    	//3、关闭连接
    	::closesocket(serverSocket);
    	::WSACleanup();	//释放winsock库
    }
    

    客户端程序:

    void UdpClient()
    {
    	//加载winsock库
    	WSADATA wsaData;
    	WORD socktVersion = MAKEWORD(2,2);	//版本号
    	if (0 != ::WSAStartup(socktVersion,&wsaData))  //加载套接字库
    	{
    		return ;
    	}
    
    	//1.建立socket
    	SOCKET clientSocket = ::socket(AF_INET,SOCK_DGRAM,0); //使用UDP协议
    	//填写服务器地址
    	sockaddr_in server_address;
    	server_address.sin_family = AF_INET;
    	server_address.sin_port = htons(6000);	//连接端口号
    	server_address.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //服务器IP地址
    
    	//2、收发数据
    	char send_buf[1024] = {0};
    	string input_str;
    	bool is_finished = false;
    	while (!is_finished)
    	{
    		cout << "Input Send Msg: ";
    		std::getline(std::cin,input_str);
    		if (input_str.empty())
    		{
    			continue;
    		}
    		if ("exit" == input_str)
    		{
    			is_finished = true;
    			continue;
    		}
    		sprintf_s(send_buf,1024,"%s",input_str.c_str());
    		::sendto(clientSocket,send_buf,strlen(send_buf),0,(sockaddr*)&server_address,sizeof(server_address)); //发送数据
    	}
    	//3、关闭连接
    	::closesocket(clientSocket);
    	::WSACleanup();	//释放winsock库
    }
  • 相关阅读:
    【BZOJ2006】[NOI2010] 超级钢琴(堆+RMQ)
    【洛谷1120】小木棍(一道有技巧的dfs)
    【BZOJ1857】传送带(分治经典:三分套三分)
    【BZOJ1045】糖果传递(基于贪心的数学题)
    【CF1000C】Covered Points Count(离散化+差分)
    【洛谷1486】[NOI2004] 郁闷的出纳员(Splay的小运用)
    【洛谷1156】垃圾陷阱(动态规划)
    严格次小生成树学习笔记
    高斯消元入门
    【洛谷4011】孤岛营救问题(状压SPFA)
  • 原文地址:https://www.cnblogs.com/cmranger/p/4783760.html
Copyright © 2011-2022 走看看