1.网络模型包含,OSI七层模型,TCP/IP模型
2.链路层,主要功能是在两个网络实体之间提供数据链路连接,其中主要使用的协议是ARP协议
3.网络层,主要作用是实现远程设备连接,其中主要使用协议是IP协议
4.传输层,主要是对数据包的分割,重组,排序,重传和连接保证数据准确到达另一端TCP/UDP
5.应用层,主要面对用户,常见协议,DNS,HTTP,POP3,SMTP,Telent
6.协议栈,一组协议系统工作
7.数据包分析和嗅探,主要功能是,收集网络链路上的二进制数据源,转换二进制可读形式,分析统计
windows下套接字编程
通过自己编写程序,实现对图片的简单加密(使用最简单加密方式xor)发送,在服务端接收到数据后进行解密,并正确显示,同时使用Wireshark进行抓包练习,抓取该数据包找到对应的图片数据,
Wireshark工具学习:《Wireshark 数据包分析实战(第二版)》
思路:1.完成程序的编写,
服务端代码:WinSockDemo.cpp,
// WinSockDemo.cpp : 定义控制台应用程序的入口点。
//Server
//1.包含头文件及库
//2.初始化环境
//3.绑定
//4.监听
//5.接收
//6.收发消息
#include "stdafx.h"
#include <WinSock2.h>
#include <fstream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
//数据解密
char *XorData(char *pData, int nSize)
{
for (int i = 0; i < nSize; i++)
{
pData[i] = pData[i] ^ 0x97;
}
return pData;
}
int _tmain(int argc, _TCHAR* argv[])
{
//1.初始化环境
WSADATA wsd = {};
if (WSAStartup(MAKEWORD(2, 2), &wsd))
{
printf("初始化环境失败!");
return 0;
}
//判断版本号
if (!(LOBYTE(wsd.wVersion) == 2 &&
HIBYTE(wsd.wVersion) == 2))
{
printf("版本号不匹配!");
WSACleanup();
return 0;
}
//2.创建套接字
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockServer == INVALID_SOCKET)
{
printf("创建套接字失败!");
WSACleanup();
return 0;
}
//3.绑定地址端口号
SOCKADDR_IN addrServer = {};
addrServer.sin_family = AF_INET;
addrServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.245");// 192.168.43.110
addrServer.sin_port = htons(1234);
int nRet = bind(sockServer, (sockaddr*)&addrServer, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
printf("绑定失败!");
closesocket(sockServer);
WSACleanup();
return 0;
}
//4.监听
nRet = listen(sockServer, 5);
if (nRet == SOCKET_ERROR)
{
printf("监听失败!");
closesocket(sockServer);
WSACleanup();
return 0;
}
//5.接收连接
SOCKADDR_IN addrClient = {};
int nSize = sizeof(SOCKADDR_IN);
SOCKET sockClient = accept(sockServer, (sockaddr*)&addrClient, &nSize);
if (nRet == SOCKET_ERROR)
{
printf("连接失败!");
closesocket(sockServer);
WSACleanup();
return 0;
}
//6.收消息
nRet = send(sockClient, "Server:link success!", strlen("Server:link success!"), 0);
if (nRet == SOCKET_ERROR)
{
closesocket(sockClient);
closesocket(sockServer);
WSACleanup();
return 0;
}
//收消息
CHAR recvBuf[1024] = {};
nRet = recv(sockClient, recvBuf, 1024, 0);
if (nRet == SOCKET_ERROR)
{
closesocket(sockClient);
closesocket(sockServer);
WSACleanup();
return 0;
}
printf("%s", recvBuf);
//接收由客户端发送的图片
//创建文件
CHAR szName[10] = {};
sprintf_s(szName, "2.jpg");
ofstream outFile(szName, ios_base::binary);
//保存接收到的图片
while (true)
{
char bufRecv[1024] = {};
nRet = recv(sockClient, bufRecv, 1024, 0);
//解密
char *pData = XorData(bufRecv, nRet);
if (nRet == SOCKET_ERROR)
{
break;
}
else if (nRet < 1024 && nRet>0)
{
//最后的数据
outFile.write(pData, nRet);
outFile.close();
break;
//continue;
}
else if (nRet == 1024)
{
//正常读取
outFile.write(pData, nRet);
//Sleep(100);
//outFile.flush();
}
}
closesocket(sockClient);
closesocket(sockServer);
WSACleanup();
system("pause");
return 0;
}
客户端代码:WinSockDemoClient.cpp,
// WinSockDemoClient.cpp : 定义控制台应用程序的入口点。
//Client
//0.包含头文件及库
//1.初始化编程环境
//2.创建套接字
//3.连接
//4.收发消息
#include "stdafx.h"
#include <fstream>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
//获取图片到缓冲区
char* ReadJpgFile(int &nSize)
{
//打开文件
ifstream inFile("1.jpg", ios_base::binary);
//获取文件大小
inFile.seekg(0, ios::end);
nSize = (int)inFile.tellg();
inFile.seekg(0, ios::beg);
//读取文件
char* pRead = new char[nSize]{};
inFile.read(pRead, nSize);
return pRead;
}
//数据加密
char *XorData(char *pData, int &nSize)
{
for (int i = 0; i < nSize; i++)
{
pData[i] = pData[i] ^ 0x97;
}
return pData;
}
int _tmain(int argc, _TCHAR* argv[])
{
//1.初始化编程环境
WSADATA wsd = {};
if (WSAStartup(MAKEWORD(2, 2), &wsd))
{
printf("初始化环境失败!");
return 0;
}
//判断版本
if (!(LOBYTE(wsd.wVersion) == 2 &&
HIBYTE(wsd.wVersion) == 2))
{
printf("版本号检测失败!");
WSACleanup();
return 0;
}
//2.创建套接字
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockClient == INVALID_SOCKET)
{
printf("创建套接字失败!");
WSACleanup();
return 0;
}
//3.连接服务器
SOCKADDR_IN addrServer = {};
addrServer.sin_family = AF_INET;
addrServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.245");// 192.168.43.110
addrServer.sin_port = htons(1234);
int nRet = connect(sockClient, (sockaddr*)&addrServer, sizeof(sockaddr));
if (sockClient == SOCKET_ERROR)
{
printf("连接失败!");
closesocket(sockClient);
WSACleanup();
return 0;
}
//4.收消息
CHAR recvBuf[1024] = {};
nRet = recv(sockClient, recvBuf, 1024, 0);
if (nRet == SOCKET_ERROR)
{
closesocket(sockClient);
WSACleanup();
return 0;
}
printf("%s", recvBuf);
//发消息
nRet = send(sockClient, "Client:link success!", strlen("Client:link success!"), 0);
if (nRet == SOCKET_ERROR)
{
closesocket(sockClient);
WSACleanup();
return 0;
}
//发送图片
//1.读取文件到缓冲区
int nSize = 0;
char *pRead = ReadJpgFile(nSize);
//数据加密
char *pData = XorData(pRead, nSize);
//2.发送图片
while (true)
{
char p[1024] = {};
memcpy(p, pData, 1024);
nRet = send(sockClient, p, 1024, 0);
pData += 1024;
nSize -= 1024;
if (nSize < 1024)
{
memcpy(p, pData, nSize);
nRet = send(sockClient, p, nSize, 0);
printf("发送图片完成!");
delete[] pRead;
delete[] pData;
pRead = nullptr;
pData = nullptr;
closesocket(sockClient);
WSACleanup();
system("pause");
return 0;
}
}
closesocket(sockClient);
WSACleanup();
system("pause");
return 0;
}
2.打开Wireshark工具选择对应的网卡,开始进行抓包,由于直接在本机进行测试,因此直接添加过滤数据包条件ip.dst == 192.168.1.245 && ip.src == 192.168.1.245,过滤数据包,然后本机抓取本机数据包需要添加一条静态路由,使用命令route add 192.168.1.245 mask 255.255.255.255 192.168.1.1,即可抓取本地数据包。