zoukankan      html  css  js  c++  java
  • Windows下socket编程(console非MFC)

    console控制台:使用<winsock2.h> 和 ws2_32.lib  参考:孙鑫C++课程14

    TCP:面对连接的、安全的通信

    ////// TcpSrv.cpp /////////
    
    #define _CRT_SECURE_NO_WARNINGS //用sprintf,而不必强制使用sprintf_s 不报错
    
    #include <winsock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    void main()
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int err;
    	wVersionRequested = MAKEWORD(1, 1);
    	//WSAStartup() initiates use of Ws2_32.dll by a process.
    	err = WSAStartup(wVersionRequested, &wsaData);
    	if (err != 0) {
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 ||
    		HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return;
    	}
    
    	//1.创建流式套接字,基于TCP(SOCK_STREAM)
    	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    	//socket地址结构体
    	SOCKADDR_IN addrSrv;//除了sin_family,其余都需要转换为网络字节序
    	addrSrv.sin_family = AF_INET;
    	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格式, INADDR_ANY表示接受多个IP地址的回应信息
    	addrSrv.sin_port = htons(6000);//端口6000,转换unsigned short为网络字节序
    	//2.将套接字绑定到一个端口号和本地地址上
    	bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    	//3.监听
    	listen(sockSrv, 5);
    	//
    	SOCKADDR_IN addrClient;//定义用来接收客户端Socket的结构体
    	int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化
    	//4.循环等待接受客户端发送请求
    	while (true)
    	{
    		//等待客户请求到来;当请求到来后,接受连接请求,
            //返回一个新的对应于此次连接的套接字(sockConnect)。
    		//接受Client请求,阻塞
    		SOCKET sockConnect = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
    		//发送数据
    		char buf[100];//inet_ntoa(addrClient.sin_addr)将IP地址转换为字符串,像 "192.168.0.5"
    		sprintf(buf, "Welcome %s to my little world.", inet_ntoa(addrClient.sin_addr));
    		send(sockConnect, buf, strlen(buf) + 1, 0);//多发一个,为了结尾
    		//接收数据
    		char recvBuf[100] = { 0 };
    		recv(sockConnect, recvBuf, sizeof(recvBuf), 0);
    
    		cout << recvBuf << endl;
    
    		//5.关闭socket
    		closesocket(sockConnect);
    	}
    
    //	WSACleanup();
    
    	return ;
    }
    
    //////////////////////////////////////////////////////////
    ///////// TcpClient.cpp  ////////////
    
    #define _CRT_SECURE_NO_WARNINGS //用sprintf,而不必强制使用sprintf_s 不报错
    
    #include <winsock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    void main()
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int err;
    	wVersionRequested = MAKEWORD(1, 1);
    	//WSAStartup() initiates use of Ws2_32.dll by a process.
    	err = WSAStartup(wVersionRequested, &wsaData);
    	if (err != 0) {
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 ||
    		HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return;
    	}
    
    	//1.创建Client端的Socket
    	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
    	//2.连接Server地址
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_family = AF_INET;
    	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//inet_addr 将IP字符串转为ULONG类型数值
    	addrSrv.sin_port = htons(6000);//Port:6000
    	connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    	//接收
    	char recvBuf[100] = { 0 };
    	recv(sockClient, recvBuf, sizeof(recvBuf), 0);
    	cout << recvBuf << endl;
    	//发送
    	char* buf = "This is lisi.";
    	send(sockClient, buf, strlen(buf) + 1, 0);
    	//3.关闭套接字
    	closesocket(sockClient);
    	WSACleanup();//终止套接字库的使用
    }
    

    总结:
    TCP服务端
    1. 创建流套接字(SOCK_STREAM)sockSrv
    2. 绑定本地IP地址和端口 bind(...)
    3. 监听 listen(...)
    4. 等待Client端连接 accept(...) 此函数获得Client端的SOCKADDR(包括IP地址,端口等)
    5. 发送数据或接收数据 send( ) / recv( )
    6. 关闭套接字
    TCP客户端
    1. 创建流套接字
    2. 连接Server端,connect( )
    3. 发送或接收数据 send recv
    4. 关闭套接字

    UDP服务器端
    1. 创建数据报套接字(SOCK_DGRAM)sockSrv
    2. bind 本地的IP地址 SOCKADDR(实际用 SOCKADDR_IN)
    3. 接收数据 recvfrom(..) 此函数保存CLient端的 SOCKADDR(IP地址等) 发送数据 sendto()
    4. 关闭套接字
    UDP客户端
    1. 创建数据报套接字(SOCK_DGRAM)sockClient
    2. 给Server端发送数据 sendto() 接收数据 recvfrom( )
    3. 关闭套接字

     UDP:面向无连接,不安全的,即时通信

    ////// UdpSrv.cpp /////////
    
    #define _CRT_SECURE_NO_WARNINGS //用sprintf,而不必强制使用sprintf_s 不报错
    
    #include <winsock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    void main()
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int err;
    	wVersionRequested = MAKEWORD(1, 1);
    	//WSAStartup() initiates use of Ws2_32.dll by a process.
    	err = WSAStartup(wVersionRequested, &wsaData);
    	if (err != 0) {
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 ||
    		HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return;
    	}
    
    	//1.创建数据报套接字,基于UDP(SOCK_DGRAM)
    	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
    	//socket地址结构体
    	SOCKADDR_IN addrSrv;//除了sin_family,其余都需要转换为网络字节序
    	addrSrv.sin_family = AF_INET;
    	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格式, INADDR_ANY表示接受多个IP地址的回应信息
    	addrSrv.sin_port = htons(6000);//端口6000,转换unsigned short为网络字节序
    	//2.将套接字绑定到一个端口号和本地地址上
    	bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    	//
    	SOCKADDR_IN addrClient;//定义用来接收客户端Socket的结构体
    	int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化
    	//接收数据 recvfrom 将Client端的IP地址,端口号等存到addrClient
    	char recvBuf[100] = { 0 };
    	recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0,(SOCKADDR*)&addrClient,&len);//阻塞
    	cout << inet_ntoa(addrClient.sin_addr)//inet_ntoa(addrClient.sin_addr)将IP地址转换为字符串,像 "192.168.0.5"
    		<< " say: "<< recvBuf << endl;
    	//发送数据 sendto
    	cout << "Please input something for sending: ";
    	char sendBuf[100];
    	gets(sendBuf);//从屏幕获取一行字符串存到sendBuf中
    	sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, len);//多发一个,为了结尾
    
    	//3.关闭socket
    	closesocket(sockSrv);
    	WSACleanup();
    
    	system("pause");
    	return;
    }
    ///////////////////////////////////////////////////////////
    
    ////// UdpClient.cpp /////////
    
    #define _CRT_SECURE_NO_WARNINGS //用sprintf,而不必强制使用sprintf_s 不报错
    
    #include <winsock2.h>
    #include <iostream>
    using namespace std;
    
    #pragma comment(lib,"ws2_32.lib")
    
    void main()
    {
    	WORD wVersionRequested;
    	WSADATA wsaData;
    	int err;
    	wVersionRequested = MAKEWORD(1, 1);
    	//WSAStartup() initiates use of Ws2_32.dll by a process.
    	err = WSAStartup(wVersionRequested, &wsaData);
    	if (err != 0) {
    		return;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 ||
    		HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return;
    	}
    
    	//1.创建套接字
    	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
    	//发送
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    	addrSrv.sin_family = AF_INET;
    	addrSrv.sin_port = htons(6000);
    	cout << "Please input something for sending: ";
    	char sendBuf[100];
    	gets(sendBuf);
    	sendto(sockClient, sendBuf, strlen(sendBuf), 0, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    	//接收数据 recvfrom 
    	char recvBuf[100] = { 0 };
    	int len = sizeof(SOCKADDR);
    	recvfrom(sockClient, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&addrSrv, &len);//阻塞
    	cout << inet_ntoa(addrSrv.sin_addr)//inet_ntoa(addrClient.sin_addr)将IP地址转换为字符串,像 "192.168.0.5"
    		<< " say: " << recvBuf << endl;
            //2.关闭套接字
    	closesocket(sockClient);
    	WSACleanup();
    	system("pause");
    }
    ///////////////////////////////////////////////////////////////
    

    MFC的Socket通信:使用#include <afxsock.h>中MFC封装的类CSocket

    参见:MFC中Socket网络通讯

    常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

    昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。
  • 相关阅读:
    [转]用mamcache 存储session的好处
    [转]怎么写 JQuery插件 (案例原理)
    关于查询优化
    HBase Canary
    HBase Bulk Loading
    有用的技术网站
    HBase 运维分析
    HBase rest
    hbase mlockall
    Jamon
  • 原文地址:https://www.cnblogs.com/htj10/p/11255733.html
Copyright © 2011-2022 走看看