现如今,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地址来通信。
最后,强烈建议自己把代码删了再敲一遍,检验有没有学透!