代码拉取完成,页面将自动刷新
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "CServer_UDP.h"
#include <time.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#pragma execution_character_set("utf-8")//utf-8编码文件
//服务器
CServer_UDP::CServer_UDP():m_terminal(false)
{
data_size = 0;
//capacity = MAX_size;
//open_file_flag = false;
//必须进行如下初始化, 否则socket()会返回10093错误
//初始化WSA
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0) //通过一个进程初始化ws2_32.dll
{
std::cout << "Initialize WSA failed" << std::endl;
return;
}
//初始化UDDP套接字
m_sServer = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in m_SocAddrserver;
/*
sin_family:地址族
sin_port:16位TCP/UDP 端口号
sin_addr:32位IP地址
sockaddr_in 一般变量赋值后,强制类型转换后传入用scokaddr做参数的函数。
sockaddr_in用于socket定义和赋值;sockaddr用于函数参数
*/
m_SocAddrserver.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//0
m_SocAddrserver.sin_family = AF_INET;
m_SocAddrserver.sin_port = htons(8090);
int ret = bind(m_sServer, (sockaddr*)&m_SocAddrserver, sizeof(m_SocAddrserver));
if (ret == -1)
{
std::cout << "bind failed!" << std::endl;
WSACleanup();
}
else
{
//此处必须赋初值,不然会导致服务器端无法正常发送
int len_Client = sizeof(sockaddr);
char recBuf[1025];
//todo:之后用Qt在界面中先输入接收端的配置信息。这里主要是为了,得到客服端的配置信息,为之后向客服端发消息做准备。
int len = recvfrom(m_sServer, recBuf, 1024, 0, (sockaddr*)&m_SocAddrClient, &len_Client);
if (len > 0)
{
//recBuf[len] = '\0';
//std::cout << "client message:" << recBuf << std::endl;
//std::cout << "get client config \n";
std::cout << "connection established\n ";
}
}
}
//服务器只接收不发送
void CServer_UDP::SendMsg(const char sendBuf[])
{
auto ret = sendto(m_sServer, sendBuf, strlen(sendBuf), 0, (sockaddr*)&m_SocAddrClient, sizeof(m_SocAddrClient));
if (ret == -1)
{
std::cout << "send failed" << std::endl;
std::cout << GetLastError()<< std::endl;
}
}
void CServer_UDP::RecMsg()
{
char recBuf[1025];
fd_set fdRead;
timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
while (!m_terminal)
{
/*设置UDP接收超时,目前为阻塞时接收,设置阻塞\超时时间,
目前存在问题因为,如果文件一直打开在写数据,何时关闭文件???
解决方法:1、传输前面的文件会因为存满字节数自动关闭
2、设置超时时间,比如等待5s中,先判断文件是否关闭然后在关闭最后一个文件
到时候实测可能存在的问题
1、1024个缓冲区够用吗?
2、存文件的速度能赶得上数据传输速度吗?
*/
FD_ZERO(&fdRead);
FD_SET(m_sServer,&fdRead);
int ret = select(0, &fdRead, NULL, NULL, &timeout);
if (ret == 0 ) //超时
{
if (ofile.is_open()) {//超时 文件还处于打开状态 关闭文件
ofile.close();
data_size = 0;
std::cout << "time out close file!\n";
}
}
else if(ret==SOCKET_ERROR)//出错
{
std::cout << "SOCKET_ERROR error\n";
}
else if (ret > 0)
{
int len = recvfrom(m_sServer, recBuf, 1024, 0, 0, 0);
if (!ofile.is_open())//还没打开文件
{
openFile();
}
if (data_size +len > MAX_size) //当前文件存不下读取的len长度的数据。
{
auto capacity = MAX_size - data_size;//当前文件的容量
if (ofile.is_open()) {
ofile.write(recBuf, capacity * sizeof(char));//将当前文件存满了
ofile.close();
int nowSize = len - capacity;//当前还有这么多数据要保存, 现在的数据长度很可能大于最大字节数量
int i = 0;
while (nowSize >= MAX_size)
{
openFile();//打开新的文件 把剩余的内容存在新的文件中
if (ofile.is_open()) {
ofile.write(recBuf + capacity+i* MAX_size, MAX_size * sizeof(char));
ofile.close();
i++;
nowSize -= MAX_size;
}
}
if (nowSize > 0)
{
openFile();//打开新的文件 把剩余的内容存在新的文件中
if (ofile.is_open()) {
ofile.write(recBuf + capacity + i * MAX_size, nowSize * sizeof(char));//还没存满不能关闭文件
data_size = nowSize;
}
}
else if(nowSize==0){
data_size = 0;
}
}
}
else if (data_size + len <= MAX_size&&ofile.is_open())//还能存下直接将所有数据存入当前文件
{
ofile.write(recBuf, len* sizeof(char));
data_size += len;
}
else {
std::cout << "error\n";
}
}
else {
std::cout << "error222\n";
}
}
}
CServer_UDP::~CServer_UDP()
{
closesocket(m_sServer);
WSACleanup();
}
void CServer_UDP::getTimeToFileName(std::string & m_file_name)
{
time_t timep;
time(&timep);
char tmp[125];
tm tm1;
localtime_s(&tm1, &timep);
strftime(tmp, sizeof(tmp), "%Y-%m-%d_%H-%M-%S", &tm1);
m_file_name = tmp;
if (m_file_name == m_file_name_last) {//和上一次的文件名相同就添加后缀_1
m_file_name += "_1";
}
m_file_name_last = m_file_name;
}
void CServer_UDP::openFile()
{
//可以用c++ 的ofstream 也可用c的fopen
//考虑到写文件的速度用c语言的API
//ofile.open();
//file = fopen("udp_data.txt", "w");//新写一个函数获取当地时间,用时间命名文件名 todo:之后修改为二进制保存,目前方便调试
if (ofile.is_open()) {
ofile.close();
}
getTimeToFileName(m_file_name);
ofile.open(m_file_name + ".txt", std::ios::out);//文件文本输出,调试好以后更改为二进制输出
std::cout <<std::endl<< m_file_name << std::endl;
if (ofile.is_open()) std::cout << "open file sucessfully!" << std::endl;
}
void CServer_UDP::closeFile()
{
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。