C++ Windows下Socket通信

现如今,Socket通信已成为主流,想用C++编写Windows下的Socket套接字程序吗?来看看吧。

既然是网络通信,那就必须要有一个客户端(client.cpp)和服务器端(server.cpp)。

要编写Socket套接字程序,那必然要用WinSock2.h和ws2_32.lib(也要用一些其他头文件辅助)。

//导入模块
#include 
#include 
#include 
#include 
#include 
#include 
//加载lib
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
//使用命名空间
using namespace std;

还需要初始化dll和创建套接字:

//初始化dll
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//           ↑                    ↑
//    WinSock规范的版本号   指向WSAData的指针

//创建套接字
SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//                      ↑         ↑                  ↑
//              IP地址类型 套接字类型(数据传输方式) 传输协议
//                 IPv4       流格式套接字          TCP传输协议
//注:sock是在cilent.cpp中的,在server.cpp中是servSock(只是变量名不同,其他无异)

接着,server.cpp需要绑定套接字,cilent.cpp需要向服务器(server.cpp)发送请求

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地址(127.0.0.1代表本机)
sockAddr.sin_port = htons(1234);  //端口
//server.cpp
bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR)); //将套接字与IP绑定
//cilent.cpp
connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

搞了这么多,cilent.cpp的初始化终于搞好了!接下来server.cpp还要进入监听状态和接收客户端的请求:

//进入监听状态
listen(servSock, 20);
//     ↑         ↑
//   套接字 请求队列的最大长度

//接收客户端请求
SOCKADDR clntAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
//                       ↑               ↑                  ↑
//               服务器端套接字          对象       长度(SOCKADDR的)

接下来,我们要让cilent.cpp不接收服务器端传回的消息,server.cpp要根据用户输入,给cilent.cpp传消息:

//cilent.cpp
while (true)
{
	//接收服务器传回的数据
	char szBuffer[MAXBYTE] = { 0 }; //全部初始化为0
	int can=recv(sock, szBuffer, MAXBYTE, NULL); //接收数据
	string buffer = szBuffer; //转为string(更好用)
	if (buffer == "exit") //退出信号
	{
		printf("对方关闭了Socket。\n"); //提示语
		closesocket(sock); //关闭套接字
		WSACleanup(); //终止使用 DLL
		system("pause"); //等待按下任意键
		exit(0); //退出
	}
	//输出接收到的数据
	printf("从server接收到的数据: %s\n",\
        buffer.size()>2?buffer.substr(1,buffer.size()-1).c_str():""); //server.cpp在数据开头和结尾都加了'k'
}
//server.cpp
while (true)
{
	printf("输入要发送的数据(要退出输入exit):"); //提示语
	//向客户端发送数据
	string str; //好用
	getline(cin, str); //获取一行
	if(str!="exit") //不是退出信号
        send(clntSock,("k"+str+"k").c_str(),str.size()+sizeof(char),NULL); //开头结尾都加'k'再发送
	else //是退出信号
	{
		send(clntSock, "exit", 4 + sizeof(char), NULL); //发送"exit"
		break; //退出循环
	}
}
printf("成功退出!\n"); //提示语
//关闭套接字
closesocket(clntSock);
closesocket(servSock);
WSACleanup();//终止DLL的使用
system("pause"); //按下任意键退出

至此,我们就搞好了通信的程序(很抱歉,只能给本机发消息),现在我给出完整程序:

server.cpp(先运行)

//导入模块
#include 
#include 
#include 
#include 
#include 
#include 
//加载lib
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
//使用命名空间
using namespace std;


int main() {
	//初始化 DLL
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//创建套接字
	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("192.168.101.7");  //具体的IP地址
	sockAddr.sin_port = htons(1234);  //端口
	bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

	//进入监听状态
	listen(servSock, 20);

	//接收客户端请求
	SOCKADDR clntAddr;
	int nSize = sizeof(SOCKADDR);
	SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
	while (true)
	{
		printf("输入要发送的数据(要退出输入exit):");
		//向客户端发送数据
		string str;
		getline(cin, str);
		if(str!="exit") send(clntSock, ("k" + str + "k").c_str(), str.size() + sizeof(char), NULL);
		else
		{
			send(clntSock, "exit", 4 + sizeof(char), NULL);
			break;
		}
	}
	printf("成功退出!\n");
	//关闭套接字
	closesocket(clntSock);
	closesocket(servSock);

	//终止 DLL 的使用
	WSACleanup();

	return 0;
}

cilent.cpp(后运行)

//导入模块
#include 
#include 
#include 
#include 
#include 
#include 
//加载lib
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
//使用命名空间
using namespace std;


int main() {
	//初始化DLL
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	//创建套接字
	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("192.168.101.7");
	sockAddr.sin_port = htons(1234);
	connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
	while (true)
	{
		//接收服务器传回的数据
		char szBuffer[MAXBYTE] = { 0 };
		int can=recv(sock, szBuffer, MAXBYTE, NULL);
		string buffer = szBuffer;
		if (buffer == "exit")
		{
			printf("对方关闭了Socket。\n");
			//关闭套接字
			closesocket(sock);
			//终止使用 DLL
			WSACleanup();
			system("pause");
			return 0;
		}
		//输出接收到的数据
		printf("从server接收到的数据: %s\n", buffer.size() > 2 ? buffer.substr(1, buffer.size() - 1).c_str() : "");
	}
	return 0;
}

虽然功能有限,但毕竟是可以通信的,如果你有两台(或以上)Windows电脑,就可以通过改动IP地址来通信。

最后,强烈建议自己把代码删了再敲一遍,检验有没有学透!

你可能感兴趣的:(服务器,网络,运维)