一,目的:服務器端向客戶端發送消息,客戶端接收消息並顯示出來。
環境:Win10的64位系統,VStudio2019。
二,實現步驟:
2.1 服務器端:
#include <iostream>
#include <stdio.h>
#include <WinSock2.h>
#include <WS2tcpip.h> //爲使用inetpton()或InetPton()函數做準備
#pragma comment (lib, "ws2_32.lib") //在編譯時加載 ws2_32.dll
int main()
{
//在使用DLL之前,需要調用WSAStartup()函數進行初始化,以指明WinSock規範的版本,
//初始化DLL
WSADATA wsaDATA;
//啓動,WSA(Windows Sockets Asynchronous, Windows異步套接字)的啓動命令,0表示成功
int ret_val = WSAStartup(MAKEWORD(2, 2), &wsaDATA); //ret_val代表return value
if (ret_val != 0)
{
std::cerr << "WSA failed to start up! Error code: " << WSAGetLastError() << std::endl;
system("pause");
exit(1);
}
std::cout << "WSA start up successfully..." << std::endl;
// 創建套接字
SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// 綁定套接字
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); // 每個字節都用0填充
sockAddr.sin_family = PF_INET; // 使用IPv4地址
//sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具體的IP地址,這是之前的老用法,這行會報錯,提示用新的函數inet_pton
inet_pton(PF_INET, "127.0.0.1", &sockAddr.sin_addr); //新函數,綁定IP地址,#include <WS2tcpip.h>
sockAddr.sin_port = htons(1234); // 端口
// bind()函數執行成功,返回值爲0,否則爲SOCKET_ERROR
ret_val = bind(servSock, (SOCKADDR*)& sockAddr, sizeof(SOCKADDR));
if (ret_val != 0)
{
std::cerr << "Failed to bind server socket! Error code: " << WSAGetLastError() << std::endl;
WSACleanup();
system("pause");
exit(1);
}
std::cout << "Server socket bound successfully..." << std::endl;
// 進入監聽狀態
ret_val = listen(servSock, 20);
if (ret_val == SOCKET_ERROR)
{
std::cerr << "Server socket failed to listen! Error code: " << WSAGetLastError() << std::endl;
WSACleanup();
system("pause");
exit(1);
}
std::cout << "Server socket started to listen..." << std::endl;
std::cout << "Sever started successfully..." << std::endl;
// 接收客戶端請求
SOCKADDR clntAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clntSock = accept(servSock, (SOCKADDR*)& clntAddr, &nSize);
if (clntSock == INVALID_SOCKET)
{
std::cout << "ssss " << clntSock << std::endl;
std::cerr << "Failed to accept client! Error code: " << WSAGetLastError() << std::endl;
WSACleanup();
system("pause");
exit(1);
}
std::cout << "ssss " << clntSock << std::endl;
// 向客戶端發送數據
const char* str = "Hello World!"; // 注意這裏必須是const char* 類型
send(clntSock, str, strlen(str) + sizeof(char), NULL);
// 關閉套接字
closesocket(clntSock);
closesocket(servSock);
// 終止DLL的使用
WSACleanup();
return 0;
//std::cout << "Hello World!\n";
}
2.2 客戶端:
#include <iostream>
#include <stdlib.h>
#include <WinSock2.h>
#include <WS2tcpip.h> // 使用inet_pton()或Inet_Pton()函數
#pragma comment(lib, "ws2_32.lib") // 在編譯時加載 ws2_32.dll
int main()
{
// 初始化DLL
WSADATA wsaData;
// WSA(Windows Sockets Asynchronous, Windows異步套接字)的啓動命令,0表示成功
int ret_val = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret_val != 0)
{
std::cerr << "WSA failed to start up! Error doce: " << WSAGetLastError() << std::endl;
system("pause");
exit(1);
}
std::cout << "WSA start up successfully..." << std::endl;
// 創建套接字
SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// 向服務器發起請求
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); // 每個字節都用0填充
sockAddr.sin_family = PF_INET;
//sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具體的IP地址,這是之前的老用法,這行會報錯,提示用新的函數inet_pton
inet_pton(PF_INET, "127.0.0.1", &sockAddr.sin_addr); //使用新函數,綁定IP地址,#include <WS2tcpip.h>
sockAddr.sin_port = htons(1234);
connect(sock, (SOCKADDR*)& sockAddr, sizeof(SOCKADDR));
// 接收服務器傳回的數據
char szBuffer[MAXBYTE] = { 0 };
recv(sock, szBuffer, MAXBYTE, NULL);
// 輸出接收到的數據
printf("Message from server: %s\n", szBuffer);
// 關閉套接字
closesocket(sock);
// 終止使用DLL
WSACleanup();
system("pause");
return 0;
//std::cout << "Hello World!\n";
}
三:運行及結果:
3.1 先運行服務器端的程序:
3.2 再運行客戶端的程序:
3.3 在客戶端這裏按下任意鍵:
3.4 查看服務器端:
參考:
http://c.biancheng.net/view/2129.html