特别鸣谢(44条消息) C++ UDP发送接收文件(BMP)_我不在你不在的博客-CSDN博客
里面一些概念:
ip地址:电脑门牌号
端口号:做这件事的行动代号
协议:接收方和发送方都必须遵守的一种规则
socket是基于tcp/ip协议发送数据技术
这东西我也讲不太明白
详情原理见(44条消息) Socket通信原理探讨(C++为例)_Syymaily的博客-CSDN博客
总之我们要做的就是
写两个c艹程序
开两个窗口
接收方先运行等着接收
发送方运行发送指定文件的数据
接收方把数据下载到指定文件夹
(一次别发太多)
难点还是在搞明白每个花里胡哨的函数都是干嘛的
原作者debug感觉挺好用的,走到那步停了可以及时发现
还有就是原程序会丢包,我把发送文件sleep了一下,就能完整发过来了
整个过程除了调参就是一大大堆莫名其妙的bug,这里举几个大家可能遇到的
如果vs报错 fopen : This function or variable may be unsafe. Consider using fopen_s instead.....之类的 把fopen函数改成对应格式的fopen_s即可
如果你的vs把这里的文件地址标红了
我们依次点击项目--属性--高级下面的字符集
把字符集改成使用多字节字符集即可
如果你的vs把inet_addr标红了,或提示错误 C4996 inet_addr : Use inet_pton() or InetPton() instead or define #%¥……%%#%¥%……&%¥乱七八糟的
表示这是老函数,他更新之后不能用了,我们直接告诉他我就用,你说话不好使
点击项目--属性--c++--常规
把SDL检查改成否
还有就是端口号一定一定要相同
也许你也会调出一大坨不知名bug,不要急,直接百度或csdn错误提示一般都可以找到解决方法
祝大家一次性成功
我的代码如下 全程vs
发送文件(client)客户端
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
#define DEST_PORT 3000
#define MAX_DATA 51200 //50kb
#define DEST_IP_ADDRESS "127.0.0.1" //"192.168.1.113"//"10.42.0.1" //"192.168.1.19"//"169.254.9.36"
#ifndef bool
#define bool int
#define true 1
#define false 0
#endif
int main(int argc, char* argv[])
{
WORD ver;
WSADATA WSAData;
ver = MAKEWORD(1, 1);
if (WSAStartup(ver, &WSAData))
{
return 0;
}
if (LOBYTE(WSAData.wVersion) != 1 ||
HIBYTE(WSAData.wVersion) != 1)
{
WSACleanup();
return 0;
}
//与本地IP绑定
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrS;
addrS.sin_addr.s_addr = htonl(INADDR_ANY);
addrS.sin_family = AF_INET;
addrS.sin_port = htons(9999);
bind(sock, (SOCKADDR*)&addrS, sizeof(SOCKADDR));
//接收端的IP地址
SOCKADDR_IN addrR;
addrR.sin_addr.s_addr = inet_addr("127.0.0.1");
addrR.sin_family = AF_INET;
addrR.sin_port = htons(9999);
int len = sizeof(SOCKADDR);
//打开要发送文件
BOOL bSuccess;
HANDLE hFile;
DWORD dwFileSize, dwHighSize, dwBytesRead;
hFile = CreateFile("D:\\Cpan\\Download\\eyes\\xw.bmp", GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
//"d:\\x.bmp"
if (hFile == INVALID_HANDLE_VALUE)
{
printf("hfle");
getchar();
return 0;
}
dwFileSize = GetFileSize(hFile, &dwHighSize);//获得文件的大小
if (dwHighSize)
{
CloseHandle(hFile);
printf("hfle2");
getchar();
return 0;
}
//发送文件大小
char strFileSize[20];
_itoa_s(dwFileSize, strFileSize, 10);
sendto(sock, strFileSize, 20, 0, (SOCKADDR*)&addrR, len);
//读文件内容到readfile中
BYTE* readfile;
readfile = (BYTE*)malloc(dwFileSize);
bSuccess = ReadFile(hFile, readfile, dwFileSize, &dwBytesRead, NULL);
CloseHandle(hFile);
if (!bSuccess || (dwBytesRead != dwFileSize))
{
free(readfile);
printf("hfle3");
getchar();
return 0;
}
//eachSend表示每次发送字符的大小
DWORD eachSend = 50 * 1024, retval, n, yu, i, j;
BYTE eachBuf[50 * 1024];
n = dwFileSize / eachSend; //共需要几次全额发送
yu = dwFileSize % eachSend; //最后剩下的字符大小
//先发送n次全额数据
for (i = 0;i < n;i++)
{
Sleep(100);
for (j = 0;j < eachSend;j++)
{
eachBuf[j] = readfile[i * eachSend + j];
}
retval = sendto(sock, (char*)eachBuf, eachSend, 0, (SOCKADDR*)&addrR, len);
if (retval != eachSend)
{
printf("adsf");
getchar();
return 0;
}
memset(eachBuf, 0, 50 * 1024);
}
//再发送剩下的字符
for (i = 0;i < yu;i++)
{
eachBuf[i] = readfile[n * eachSend + i];
}
retval = sendto(sock, (char*)eachBuf, yu, 0, (SOCKADDR*)&addrR, len);
if (retval != yu)
{
return 0;
}
//中断winsocket库
closesocket(sock);
WSACleanup();
printf("over");
getchar();
return 0;
}
接收端(server)服务器端
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
#define SERV_PORT 3000
#define MAX_DATA 51200 //50kb
#define FILE_LENGTH 921654 //图片大小
#ifndef bool
#define bool int
#define true 1
#define false 0
#endif
int main()
{
WORD ver;
WSADATA WSAData;
ver = MAKEWORD(1, 1);
if (WSAStartup(ver, &WSAData))
{
printf("adsf2");
getchar();
return 0;
}
if (LOBYTE(WSAData.wVersion) != 1 ||
HIBYTE(WSAData.wVersion) != 1)
{
printf("adsf3");
WSACleanup();
return 0;
}
//与本地IP绑定
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrR;
addrR.sin_addr.s_addr = htonl(INADDR_ANY);
addrR.sin_family = AF_INET;
addrR.sin_port = htons(9999);
if (SOCKET_ERROR == bind(sock, (SOCKADDR*)&addrR, sizeof(SOCKADDR)))
{
printf("adsf4");
WSACleanup();
return 0;
}
//获取要接收文件的大小
SOCKADDR_IN addrS;
int len = sizeof(SOCKADDR);
char strFileSize[20];
recvfrom(sock, strFileSize, 20, 0, (SOCKADDR*)&addrS, &len);
printf("%s", strFileSize);
DWORD dwFileSize;
dwFileSize = atoi(strFileSize); //文件大小
int a = clock();
DWORD eachRecv = 50 * 1024, n, yu, i, j, retval;
n = dwFileSize / eachRecv;
yu = dwFileSize % eachRecv;
char eachBuf[50 * 1024];
printf("adsf5111\n");
BYTE* recvbuf = (BYTE*)malloc(dwFileSize);//初始化要存放数据的字符串
printf("%d\n", n);
for (i = 0;i < n;i++)
{
printf("adsf511133\n");
retval = recvfrom(sock, eachBuf, eachRecv, 0, (SOCKADDR*)&addrS, &len);
if (retval != eachRecv)
{
printf("adsf5");
return 0;
}
for (j = 0;j < eachRecv;j++)
{
recvbuf[i * eachRecv + j] = (BYTE)eachBuf[j];
}
memset(eachBuf, 0, 50 * 1024);
}
printf("114514\n");
retval = recvfrom(sock, eachBuf, yu, 0, (SOCKADDR*)&addrR, &len);
if (retval != yu)
{
printf("adsfbbbb");
return 0;
}
for (i = 0;i < yu;i++)
{
recvbuf[n * eachRecv + i] = (BYTE)eachBuf[i];
}
//写入文件
FILE* fp;
if (fopen_s(&fp, "D:\\Cpan\\Download\\eyes\\xwcon.bmp", "wb"))
return false;
fwrite(recvbuf, dwFileSize, 1, fp);
fclose(fp);
int b = clock() - a;
printf("%d", b);
//中断winsocket库
closesocket(sock);
WSACleanup();
getchar();
return 0;
}