作者:iainabaobei_151 | 来源:互联网 | 2023-09-08 14:04
今天我将分享socket编程,在这条路上的坑,我还能剩多少了!之前再linux系统下进行学习,今天尝试再window下进行编程;区别:后者需要在进行socket编程,加载socket链接库。
今天我将分享socket编程,在这条路上的坑,我还能剩多少了!
之前再linux系统下进行学习,今天尝试再window下进行编程;
区别:后者需要在进行socket编程,加载socket链接库。
server端:
#include
#include<string>
#include
using namespace std;
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define CONNECT_NUM_MAX 10 //最大连接数
#define MSG_MAX_NUM 256 //接受最大数据数
#define MY_PORT 18000 //端口
#define MY_IP 127.0.0.1 //IP
int main()
{
//0.加载套接字库
WSADATA wsaData;
int ret = 0;
if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
cout <<"WSAStartup(MAKEWORD(2, 2) execute failed!" << endl;
return -1;
}
if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
{
WSACleanup();
cout <<"WSADATA version is not correct" << endl;
return -1;
}
//1.创建套接字
SOCKET sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockSer == INVALID_SOCKET)
{
cout <<"sockSer create fail" << endl;
return -1;
}
//初始化服务器地址族变量
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(18000);
serAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int serLen = sizeof(SOCKADDR);
//2.bind链接
ret = bind(sockSer, (sockaddr *)&serAddr, serLen);
if (ret == SOCKET_ERROR)
{
cout <<"bind execute fail" << endl;
closesocket(sockSer);
WSACleanup();
return -1;
}
//3.listen监听
ret = listen(sockSer, CONNECT_NUM_MAX);
if (ret == SOCKET_ERROR)
{
cout <<"listen execute failed" << endl;
closesocket(sockSer);
return -1;
}
else
{
cout <<"Server is listening on" <":" <"." << endl;
}
//4.accept
sockaddr_in cliAddr;
int cliLen = sizeof(SOCKADDR);
SOCKET sockCli = accept(sockSer, (sockaddr *)&cliAddr, &cliLen);
if (sockCli == INVALID_SOCKET)
{
cout <<"Accepted failed with error code:%d\n" < endl;;
closesocket(sockSer);
WSACleanup();
return -1;
}
cout <<"Accepted\n" ;
//5.recv/send
char sendMsg[MSG_MAX_NUM];
char recvMsg[MSG_MAX_NUM];
while (1)
{
ZeroMemory(recvMsg, MSG_MAX_NUM); //对数组进行初始化
recv(sockCli, recvMsg, 256,0);
cout <<"Cli:>"< endl;
ZeroMemory(sendMsg, MSG_MAX_NUM);
cout <<"Ser:>";
cin >> sendMsg;
send(sockCli, sendMsg, strlen(sendMsg)+1, 0);
}
//6.close
closesocket(sockSer);
return 0;
}
坑1:在服务端,我们需要两个SOCKET对象(sockSer和sockCli),前者用来连接、监听和接受客户端请求;后者则在服务端接受客户端请求后返回的sockCli,作为在收发消息的第一个参数。
坑2:必须将客户端和服务器的端口好进行统一。
坑3:sockaddr_in 创建的结构体变量,在配置完成后,connect函数中使用需要进行强转(sockaddr *).
客户端:
#include
#include<string>
#include
using namespace std;
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define MSG_MAX_NUM 256
#define MY_IP 127.0.0.1
#define MY_PORT 18000
int main()
{
//0.加载套接字库
WSADATA wsaData;
int ret = 0;
if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
{
cout <<"WSAStartup(MAKEWORD(2, 2), &wsaData) execute failed" << endl;
return -1;
}
if (2 != LOBYTE(wsaData.wVersion) || 2 != HIBYTE(wsaData.wVersion))
{
WSACleanup();
cout <<"WSADATA version is not correct" << endl;
return -1;
}
//1.创建套接字
SOCKET sockCli = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockCli == INVALID_SOCKET)
{
cout <<"sockCli create failed" << endl;
}
//初始化客户端链接服务器端变量
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(MY_PORT);
serAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int serLen = sizeof(sockaddr);
//2.connect
ret = connect(sockCli, (sockaddr *)&serAddr, serLen);
if (ret != 0)
{
cout <<"connect failed" << endl;
closesocket(sockCli);
WSACleanup();
cin.get();
return -1;
}
//3.收发消息
char sendMsg[MSG_MAX_NUM];
char recvMsg[MSG_MAX_NUM];
while (1)
{
ZeroMemory(sendMsg, MSG_MAX_NUM);
cout <<"Cli:>";
cin >> sendMsg;
send(sockCli, sendMsg, strlen(sendMsg) + 1, 0);
ZeroMemory(recvMsg, MSG_MAX_NUM);
recv(sockCli, recvMsg, 256, 0);
cout <<"Ser:>" < endl;
}
//4.关闭套接字
closesocket(sockCli);
return 0;
}
坑1:客户端只要一个SOCKET对象,即针对服务端进行连接,发送数据;
坑2:sockaddr_in 创建的结构体变量,在配置完成后,connect函数中使用需要进行强转(sockaddr *).