溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

發(fā)布時間:2022-01-20 11:03:18 來源:億速云 閱讀:208 作者:小新 欄目:開發(fā)技術

這篇文章將為大家詳細講解有關C++ Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

    前言

    socket編程分為TCP和UDP兩個模塊,其中TCP是可靠的、安全的,常用于發(fā)送文件等,而UDP是不可靠的、不安全的,常用作視頻通話等。

    如下圖:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    頭文件與庫:

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

    準備工作:

    創(chuàng)建工程后,首先右鍵工程,選擇屬性

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    然后選擇 C/C++ - 預處理器 - 預處理器定義

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    將字符串 _WINSOCK_DEPRECATED_NO_WARNINGS 添加到里面去,點擊應用即可!

    TCP

    連接過程圖:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    創(chuàng)建tcp服務器和客戶端都是按照上圖的步驟來操作的!

    1). 服務器

    初始化套接字庫
    對應圖中socket()

    WORD wVersion;
    WSADATA wsaData;
    int err;
    
    // 設置版本,可以理解為1.1
    wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    // 啟動
    err = WSAStartup(wVersion, &wsaData);

    創(chuàng)建tcp套接字
    對應圖中socket()

    // AF_INET:ipv4   AF_INET6:ipv6
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

    綁定到本機
    對應圖中bind()

    // 準備綁定信息
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);	// 設置綁定網(wǎng)卡
    addrSrv.sin_family = AF_INET;		// 設置綁定網(wǎng)絡模式
    addrSrv.sin_port = htons(6000);		// 設置綁定端口
    // hton: host to network  x86:小端    網(wǎng)絡傳輸:htons大端
    
    // 綁定到本機
    int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

    監(jiān)聽
    對應圖中listen()

    // 同時能接收10個鏈接,主要看參數(shù)二的設置個數(shù)
    listen(sockSrv, 10);

    接收連接請求,返回針對客戶端的套接字
    對應圖中accept()

    SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);

    發(fā)送數(shù)據(jù)
    對應圖中write()

    sprintf_s(sendBuf, "hello client!\n");
    int iSend = send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);

    接收數(shù)據(jù)
    對應圖中read()

    recv(sockConn, recvBuf, 100, 0);

    關閉套接字
    對應圖中close()

    closesocket(sockConn);

    清理套接字庫

    WSACleanup();

    具體實現(xiàn)代碼

    #include <iostream>
    #include <stdio.h>
    #include <WinSock2.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    
    int main(void) {
    
    	// 1.初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	// 設置版本,可以理解為1.1
    	wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    	// 啟動
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    	// 檢查:網(wǎng)絡低位不等于1 || 網(wǎng)絡高位不等于1
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		// 清理套接字庫
    		WSACleanup();
    		return -1;
    	}
    
    	// 2.創(chuàng)建tcp套接字		// AF_INET:ipv4   AF_INET6:ipv6
    	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    
    	// 準備綁定信息
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);	// 設置綁定網(wǎng)卡
    	addrSrv.sin_family = AF_INET;		// 設置綁定網(wǎng)絡模式
    	addrSrv.sin_port = htons(6000);		// 設置綁定端口
    	// hton: host to network  x86:小端    網(wǎng)絡傳輸:htons大端
    
    	// 3.綁定到本機
    	int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    	if (retVal == SOCKET_ERROR) {
    		printf("Failed bind:%d\n", WSAGetLastError());
    		return -1;
    	}
    
    	// 4.監(jiān)聽,同時能接收10個鏈接
    	if (listen(sockSrv, 10) == SOCKET_ERROR) {
    		printf("Listen failed:%d", WSAGetLastError());
    		return -1;
    	}
    
    	std::cout << "Server start at port: 6000" << std::endl;
    
    	SOCKADDR_IN addrCli;
    	int len = sizeof(SOCKADDR);
    
    	char recvBuf[100];
    	char sendBuf[100];
    	while (1) {
    		// 5.接收連接請求,返回針對客戶端的套接字
    		SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);
    		if (sockConn == SOCKET_ERROR) {
    			//printf("Accept failed:%d", WSAGetLastError());
    			std::cout << "Accept failed: " << WSAGetLastError() << std::endl;
    			break;
    		}
    
    		//printf("Accept client IP:[%s]\n", inet_ntoa(addrCli.sin_addr));
    		std::cout << "Accept client IP: " << inet_ntoa(addrCli.sin_addr) << std::endl;
    
    		// 6.發(fā)送數(shù)據(jù)
    		sprintf_s(sendBuf, "hello client!\n");
    		int iSend = send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
    		if (iSend == SOCKET_ERROR) {
    			std::cout << "send failed!\n";
    			break;
    		}
    
    		// 7.接收數(shù)據(jù)
    		recv(sockConn, recvBuf, 100, 0);
    		std::cout << recvBuf << std::endl;
    
    		// 關閉套接字
    		closesocket(sockConn);
    	}
    
    
    	// 8.關閉套接字
    	closesocket(sockSrv);
    
    	// 9.清理套接字庫
    	WSACleanup();
    
    	return 0;
    }

    2). 客戶端

    初始化套接字庫
    對應圖中socket()

    WORD wVersion;
    WSADATA wsaData;
    int err;
    
    // 可以理解為1.1
    wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    // 啟動
    err = WSAStartup(wVersion, &wsaData);
    
    // 創(chuàng)建TCP套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);

    連接服務器
    對應圖中connect()

    // 連接服務器
    int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

    發(fā)送數(shù)據(jù)到服務器
    對應圖中write()

    char sendBuf[] = "你好,服務器,我是客戶端!";
    send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);

    接收服務器的數(shù)據(jù)
    對應圖中read()

    char recvBuf[100];
    recv(sockCli, recvBuf, sizeof(recvBuf), 0);

    關閉套接字并清除套接字庫
    對應圖中close()

    closesocket(sockCli);
    WSACleanup();

    具體實現(xiàn)代碼

    #include <iostream>
    #include <WinSock2.h>
    
    
    #pragma comment(lib, "ws2_32.lib")
    
    
    int main(void) {
    
    	// 1.初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	// 可以理解為1.1
    	wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    	// 啟動
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    	// 檢查:網(wǎng)絡地位不等于1 || 網(wǎng)絡高位不等于1
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		// 清理套接字庫
    		WSACleanup();
    		return -1;
    	}
    
    	// 創(chuàng)建TCP套接字
    	SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
    
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");	// 服務器地址
    	addrSrv.sin_port = htons(6000);		// 端口號
    	addrSrv.sin_family = AF_INET;		// 地址類型(ipv4)
    
    	// 2.連接服務器
    	int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    	if (err_log == 0) {
    		printf("連接服務器成功!\n");
    	
    	} else {
    		printf("連接服務器失??!\n");
    		return -1;
    	}
    
    
    	char recvBuf[100];
    	char sendBuf[] = "你好,服務器,我是客戶端!";
    	// 3.發(fā)送數(shù)據(jù)到服務器
    	send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);
    
    	// 4.接收服務器的數(shù)據(jù)
    	recv(sockCli, recvBuf, sizeof(recvBuf), 0);
    	std::cout << recvBuf << std::endl;
    
    
    	// 5.關閉套接字并清除套接字庫
    	closesocket(sockCli);
    	WSACleanup();
    
    	system("pause");
    
    	return 0;
    }

    運行效果:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    3). TCP聊天小項目

    下面是根據(jù)上面的代碼修改的一個聊天小項目(使用到了多線程)

    只有一個服務器,服務器一直開啟等待客戶端連接;
    客戶都安可以開啟多個,且可以一直連續(xù)的與服務器進行發(fā)送接收消息;
    服務器給客戶端發(fā)送數(shù)據(jù),得通過1 - 9來區(qū)分到底給那個客戶端發(fā)送消息,例如給第二個客戶端發(fā)送消息:2你好,客戶端
    客戶端那邊接收到的數(shù)據(jù)是:你好,客戶端

    服務器代碼

    #include <iostream>
    #include <WinSock2.h>
    #include <stdio.h>
    #include <Windows.h>
    #include <process.h>
    #include <vector>
    #include <conio.h>
    #include <string.h>
    #include <string>
    
    #pragma comment(lib, "ws2_32.lib")
    
    
    SOCKET sockSrv;
    std::vector<SOCKET> vec_sockConn;
    std::vector<SOCKADDR_IN> vec_sockaddr_in;
    std::vector<int> vec_sockIndex;
    
    
    // 這個結(jié)構(gòu)體用作線程參數(shù)
    typedef struct SERVER_CLIENT {
    	SOCKET server;
    	SOCKADDR_IN client;
    	int clientIndex;
    }SC;
    
    
    
    // 判斷有沒有斷開連接
    bool IsSocketClosed(SOCKET clientSocket) {
    	bool ret = false;
    	HANDLE closeEvent = WSACreateEvent();
    	WSAEventSelect(clientSocket, closeEvent, FD_CLOSE);
    
    	DWORD dwRet = WaitForSingleObject(closeEvent, 0);
    
    	if (dwRet == WSA_WAIT_EVENT_0)
    		ret = true;
    	else if (dwRet == WSA_WAIT_TIMEOUT)
    		ret = false;
    
    	WSACloseEvent(closeEvent);
    	return ret;
    }
    
    
    // 接收請求
    unsigned int WINAPI  ThreadAccept(LPVOID p) {
    	static int i = 0;
    	while (1) {
    		SOCKADDR_IN addrCli;
    		int len = sizeof(SOCKADDR);
    
    		// 5.接收連接請求,返回針對客戶端的套接字
    		SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrCli, &len);
    		if (sockConn == SOCKET_ERROR) {
    			printf("Accept failed:%d", WSAGetLastError());
    		}
    
    		// 存儲當前服務器與客戶端 連接綁定的socket
    		vec_sockIndex.emplace_back(i++);
    		vec_sockaddr_in.emplace_back(addrCli);
    		vec_sockConn.emplace_back(sockConn);
    
    		printf("\033[0;%d;40m客戶端[%d]上線\033[0m\n", 31, i);
    	}
    	
    
    	return 0;
    }
    
    unsigned int WINAPI  _ThreadRecv(LPVOID p) {
    	char recvBuf[100];
    	memset(recvBuf, 0, 100);
    
    	SC _sc = *(SC *)p;
    	
    	while (1) {
    		Sleep(20);
    
    		if (IsSocketClosed(_sc.server) == true) {
    			printf("客戶端 [%d] 斷開連接!\n", _sc.clientIndex + 1);
    			break;
    		}
    
    
    		// 接收數(shù)據(jù)
    		recv(_sc.server, recvBuf, 100, 0);
    		if (strlen(recvBuf) == 0) {
    			continue;
    		}
    	
    		printf("接收到客戶端 [%d] 的消息:%s\n", _sc.clientIndex + 1, recvBuf);
    		memset(recvBuf, 0, 100);
    	}
    	return 0;
    }
    
    unsigned int WINAPI  ThreadRecv(LPVOID p) {
    
    	static int index = 0;
    
    	while (1) {
    		// 還沒有客戶端與服務器進行連接
    		if (vec_sockConn.size() == 0) {
    			continue;
    		}
    
    		// 接收線程已經(jīng)開啟和客戶端個數(shù)相等
    		if (vec_sockConn.size()  == index) {
    			continue;
    		}
    
    		SC sc;
    		sc.server = vec_sockConn.at(index);
    		sc.client = vec_sockaddr_in.at(index);
    		sc.clientIndex = vec_sockIndex.at(index);
    
    		HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, _ThreadRecv, (void *)&sc, 0, NULL);
    
    		index++;
    		Sleep(20);
    	}
    
    	return 0;
    }
    
    
    
    int main(void) {
    
    	// 1.初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	// 設置版本,可以理解為1.1
    	wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    	// 啟動
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    	// 檢查:網(wǎng)絡低位不等于1 || 網(wǎng)絡高位不等于1
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		// 清理套接字庫
    		WSACleanup();
    		return -1;
    	}
    
    	// 2.創(chuàng)建tcp套接字		// AF_INET:ipv4   AF_INET6:ipv6
    	sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    
    	// 準備綁定信息
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);	// 設置綁定網(wǎng)卡
    	addrSrv.sin_family = AF_INET;		// 設置綁定網(wǎng)絡模式
    	addrSrv.sin_port = htons(6000);		// 設置綁定端口
    	// hton: host to network  x86:小端    網(wǎng)絡傳輸:htons大端
    
    	// 3.綁定到本機
    	int retVal = bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    	if (retVal == SOCKET_ERROR) {
    		printf("Failed bind:%d\n", WSAGetLastError());
    		return -1;
    	}
    
    	// 4.監(jiān)聽,同時接收10個鏈接
    	if (listen(sockSrv, 10) == SOCKET_ERROR) {
    		printf("Listen failed:%d", WSAGetLastError());
    		return -1;
    	}
    
    	std::cout << "Server start at port: 6000" << std::endl;
    
    
    	// 線程句柄				// 創(chuàng)建線程
    	HANDLE hThread_1 = (HANDLE)_beginthreadex(NULL, 0, ThreadAccept, NULL, 0, NULL);
    	HANDLE hThread_2 = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, NULL, 0, NULL);
    
    
    	//uiInit();
    	//editPrint(0, ">");
    
    
    	char sendBuf[100];
    	while (1) {
    
    		//printf("請輸入發(fā)送內(nèi)容:");
    
    		char c = getchar();				// 輸入發(fā)送給誰
    		scanf_s("%s", sendBuf, 100);	// 輸入發(fā)送的內(nèi)容
    
    		if (strlen(sendBuf) == 0) {
    			printf("輸入內(nèi)容為空或者超長!\n");
    		}
    
    		// 1 至 9
    		if (c < '1' || c > '9' || vec_sockConn.size() == 0 || c - '0' >= vec_sockConn.size() + 1) {
    			while ((c = getchar()) != '\n');	// 清空輸入緩沖區(qū)
    			memset(sendBuf, 0, 100);
    			printf("輸入內(nèi)容不符合規(guī)則!\n");
    			continue;
    		}
    
    
    
    		// 發(fā)送數(shù)據(jù)
    		int index = --c - '0';	// 因為下標是從零開始的,所以c要先自減
    		int iSend = send(vec_sockConn.at(index) , sendBuf, strlen(sendBuf) + 1, 0);
    		if (iSend == SOCKET_ERROR) {
    			std::cout << "send failed!\n";
    			break;
    		}
    
    
    		memset(sendBuf, 0, 100);
    		while ((c = getchar()) != '\n');	// 清空輸入緩沖區(qū)
    	}
    
    	// 關閉套接字
    	std::vector<SOCKET>::iterator it = vec_sockConn.begin();
    	for (; it != vec_sockConn.end(); it++) {
    		closesocket((SOCKET)(*it));
    	}
    
    
    	WaitForSingleObject(hThread_1, INFINITE);
    	WaitForSingleObject(hThread_2, INFINITE);
    
    	CloseHandle(hThread_1);
    	CloseHandle(hThread_2);
    
    	// 7.關閉套接字
    	closesocket(sockSrv);
    
    	// 8.清理套接字庫
    	WSACleanup();
    
    	return 0;
    }

    客戶端

    #include <iostream>
    #include <WinSock2.h>
    #include <process.h>
    #include <stdio.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    SOCKET sockCli;
    
    
    // 判斷有沒有斷開連接
    bool IsSocketClosed(SOCKET clientSocket) {
    	bool ret = false;
    	HANDLE closeEvent = WSACreateEvent();
    	WSAEventSelect(clientSocket, closeEvent, FD_CLOSE);
    
    	DWORD dwRet = WaitForSingleObject(closeEvent, 0);
    
    	if (dwRet == WSA_WAIT_EVENT_0)
    		ret = true;
    	else if (dwRet == WSA_WAIT_TIMEOUT)
    		ret = false;
    
    	WSACloseEvent(closeEvent);
    	return ret;
    }
    
    
    unsigned int WINAPI  ThreadRecv(LPVOID p) {
    	char recvBuf[100];
    	memset(recvBuf, 0, 100);
    
    	while (1) {
    		Sleep(20);
    
    		if (IsSocketClosed(sockCli) == true) {
    			printf("服務器 斷開連接!\n");
    			break;
    		}
    
    		// 接收服務器的數(shù)據(jù)
    		recv(sockCli, recvBuf, sizeof(recvBuf), 0);
    		if (strlen(recvBuf) == 0) continue;
    
    		std::cout << recvBuf << std::endl;
    		memset(recvBuf, 0, 100);
    	}
    
    
    	return 0;
    }
    
    int main(void) {
    
    	// 1.初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	// 可以理解為1.1
    	wVersion = MAKEWORD(1, 1);	// 例:MAKEWORD(a, b) --> b | a << 8 將a左移8位變成高位與b合并起來
    
    	// 啟動
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    	// 檢查:網(wǎng)絡地位不等于1 || 網(wǎng)絡高位不等于1
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		// 清理套接字庫
    		WSACleanup();
    		return -1;
    	}
    
    	// 創(chuàng)建TCP套接字
    	sockCli = socket(AF_INET, SOCK_STREAM, 0);
    
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");	// 服務器地址
    	addrSrv.sin_port = htons(6000);		// 端口號
    	addrSrv.sin_family = AF_INET;		// 地址類型(ipv4)
    
    	// 連接服務器
    	int err_log = connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    	if (err_log == 0) {
    		printf("連接服務器成功!\n");
    
    	} else {
    		printf("連接服務器失??!\n");
    		return -1;
    	}
    
    	// 線程句柄				// 創(chuàng)建線程
    	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadRecv, NULL, 0, NULL);
    
    
    	char sendBuf[100];
    	while (1) {
    
    		//printf("請輸入發(fā)送內(nèi)容:");
    		scanf_s("%s", sendBuf, 100);
    
    		// 發(fā)送數(shù)據(jù)到服務器
    		send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);
    
    		memset(sendBuf, 0, 100);
    		char c;
    		while ((c = getchar()) != '\n');
    	}
    
    
    	WaitForSingleObject(hThread, INFINITE);
    	CloseHandle(hThread);
    
    
    	// 關閉套接字并清除套接字庫
    	closesocket(sockCli);
    	WSACleanup();
    
    	system("pause");
    
    	return 0;
    }

    運行效果:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    UDP

    UDP就比較簡單了,步驟比tcp要少一些。

    連接過程圖:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    1). 服務器

    初始化套接字庫

    WORD wVersion;
    WSADATA wsaData;
    int err;
    
    wVersion = MAKEWORD(1, 1);

    創(chuàng)建套接字

    SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);

    綁定

    // SOCKADDR_IN addrSrv; 省略了定義和賦值
    bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));

    接收數(shù)據(jù)

    char recvBuf[100];
    recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);

    發(fā)送數(shù)據(jù)

    char sendBuf[] = "hello Client,I'm Server!\n";
    sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrCli, len);

    關閉

    closesocket(sockSrv);
    WSACleanup();

    具體實現(xiàn)代碼

    #include <WinSock2.h>
    #include <iostream>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main(void) {
    	// 初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	wVersion = MAKEWORD(1, 1);
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return -1;
    	}
    
    	// 創(chuàng)建套接字
    	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
    
    	SOCKADDR_IN addrSrv;
    	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    	addrSrv.sin_family = AF_INET;
    	addrSrv.sin_port = htons(6001);
    
    	// 綁定到本機6001端口
    	bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
    
    	// 接收請求,處理請求
    	SOCKADDR_IN addrCli;
    	int len = sizeof(SOCKADDR);
    
    	char sendBuf[] = "hello Client,I'm Server!\n";
    	char recvBuf[100];
    
    	std::cout << "start UDP server with port 6001" << std::endl;
    	while (1) {
    		// 接收數(shù)據(jù)
    		recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);
    		std::cout << "Recv:" << recvBuf << std::endl;
    
    		// 發(fā)送數(shù)據(jù)
    		sendto(sockSrv, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrCli, len);
    		std::cout << "Send:" << sendBuf << std::endl;
    	}
    
    	closesocket(sockSrv);
    	WSACleanup();
    
    	return 0;
    }

    2). 客戶端

    初始化套接字庫

    WORD wVersion;
    WSADATA wsaData;
    int err;
    
    wVersion = MAKEWORD(1, 1);

    創(chuàng)建UDP套接字

    SOCKET sockCli = socket(AF_INET, SOCK_DGRAM, 0);
    SOCKADDR_IN addrSrv;

    接收數(shù)據(jù)

    char recvBuf[100];
    recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);

    發(fā)送數(shù)據(jù)

    char sendBuf[] = "hello Client,I'm Server!\n";
    sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrSrv, len);

    關閉

    closesocket(sockSrv);
    WSACleanup();

    具體實現(xiàn)代碼

    #include <WinSock2.h>
    #include <iostream>
    
    #pragma comment(lib, "ws2_32.lib")
    
    
    int main(void) {
    
    	// 初始化套接字庫
    	WORD wVersion;
    	WSADATA wsaData;
    	int err;
    
    	wVersion = MAKEWORD(1, 1);
    	err = WSAStartup(wVersion, &wsaData);
    	if (err != 0) {
    		return err;
    	}
    
    	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
    		WSACleanup();
    		return -1;
    	}
    
    	// 創(chuàng)建UDP套接字
    	SOCKET sockCli = 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(6001);
    
    	SOCKADDR_IN addrCli;
    	int len = sizeof(SOCKADDR);
    
    	char sendBuf[] = "hello, I'm Client!\n";
    	char recvBuf[100];
    
    	std::cout << "send to Server: " << sendBuf << std::endl;
    	sendto(sockCli, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrSrv, len);
    
    	recvfrom(sockCli, recvBuf, 100, 0, (SOCKADDR *)&addrCli, &len);
    	std::cout << "recv from: " << recvBuf << std::endl;
    
    
    	closesocket(sockCli);
    	WSACleanup();
    
    	system("pause");
    	return 0;
    }

    運行效果:

    C++?Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程

    關于“C++ Socket如何實現(xiàn)TCP與UDP網(wǎng)絡編程”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

    AI