C++ 基於Socket的UDP網絡編程(IPv4)

UDP的客戶端:

#include <iostream>
#include<winsock2.h>
using namespace std;

#pragma comment(lib,"ws2_32.lib")

//UDP客戶端
int main()
{
	//初始化winsock環境
	WSADATA wd;//程序輸出的
	if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//成功返回0
	{
		cout << "WSAStartup error" << GetLastError() << endl;
		return 0;
	}

	//1.創建UDP數據報嵌套字,SOCK_DGRAM數據包
	SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == INVALID_SOCKET)
	{
		cout << "socket error" << GetLastError() << endl;
		return 0;
	}
	
	//2.接收或發送數據 recvfrom , sendto不同於TCP的recv與send
	//服務器的地址
	sockaddr_in addr;//sockaddr變種
	addr.sin_port = htons(8000);//網絡字節序,端口號
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//ip地址
	addr.sin_family = AF_INET;//地址族
	int len = sizeof(sockaddr_in);//指定大小

	int ret = 0;
	do
	{
		//直接使用上面的客戶端地址
		sendto(s, "I am Clinet!", strlen("I am Server!"), 0, (SOCKADDR*)&addr, len);


		char buf[100] = { "\0" };
		//recvfrom默認是阻塞的,也就是說沒有數據過來會一直等待
		ret = recvfrom(s, buf, 100, 0, NULL, NULL);//不需要服務端地址
		cout << "recvfrom " << ret << ":  " << buf <<endl;
		Sleep(1000);
	} while (ret != 0 && ret != SOCKET_ERROR);//0對方關閉套接字

	//3.關閉套接字
	closesocket(s);

	//清理winsock2環境
	WSACleanup();
	return 0;
}

UDP服務端:

#include <iostream>
#include<winsock2.h>
using namespace std;

#pragma comment(lib,"ws2_32.lib")

//UDP服務端
int main()
{
	//初始化winsock環境
	WSADATA wd;//程序輸出的
	if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//成功返回0
	{
		cout << "WSAStartup error" << GetLastError() << endl;
		return 0;
	}

	//1.創建UDP數據報嵌套字
	SOCKET s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if (s == INVALID_SOCKET)
	{
		cout << "socket error" << GetLastError() << endl;
		return 0;
	}

	//2.綁定到IP地址和端口
	sockaddr_in addr;
	addr.sin_port = htons(8000);//網絡字節序
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");//s_addr是一個宏與S_un.S_addr相同
	addr.sin_family = AF_INET;
	int len = sizeof(SOCKADDR);
	if (bind(s, (SOCKADDR*)&addr, len) == SOCKET_ERROR)
	{
		cout << "bind error" << GetLastError() << endl;
		return 0;
	}
	//超時斷開連接
	int nNetTimeout = 5000;//5s
	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&nNetTimeout, sizeof(int)) == SOCKET_ERROR)
	{
		cout << "setsockopt error" << GetLastError() << endl;
		return 0;
	}

	//3.接收或發送數據 recvfrom , sendto不同於TCP的recv與send
	int ret = 0;
	do
	{
		//接受客戶端的地址
		sockaddr_in addrClient;
		memset(&addrClient,0,sizeof(addrClient));
		int len = sizeof(SOCKADDR);//需要復值結構體的長度
		char buf[100] = {"\0"};
		//recvfrom默認是阻塞的,也就是說沒有數據過來會一直等待
		ret = recvfrom(s,buf,100,0,(SOCKADDR*)&addrClient,&len);//成功返回接受字數,錯誤返回SOCKET_ERROR
		cout << "recvfrom " << ret << ":  " << buf <<endl;

		//直接使用上面的客戶端地址
		sendto(s,"I am Server!",strlen("I am Server!"),0,(SOCKADDR*)&addrClient,len);

	} while (ret != 0 && ret != SOCKET_ERROR);//0對方關閉套接字

	//4.關閉套接字
	closesocket(s);

	//清理winsock2環境
	WSACleanup();
	return 0;
}

 先運行服務端再運行客戶端

代碼:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章