Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ikcp_recv总是返回-2,ikcp_peeksize函数里的kcp->nrcv_que与seg->frg这两个变量是什么意思 #414

Closed
HeYang6 opened this issue Jun 26, 2024 · 3 comments

Comments

@HeYang6
Copy link

HeYang6 commented Jun 26, 2024

我做的是一个简单的文件上传下载功能,几KB的文件没有问题,超过1M的文件就出现问题了
因为if (kcp->nrcv_que < seg->frg + 1) return -1;这行代码导致调用的ikcp_recv总是返回-2,帮忙看下是怎么回事,顺便告诉我下kcp->nrcv_que与seg->frg变量的含义,谢谢

image
image
image
image

发送端代码
#include <stdio.h>
#include <stdlib.h>
#include "..\test.h"
#include <ikcp.h>
#include
#include <winsock.h>
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
sockaddr_in addr;
int udp_send(const char *buf, int len, ikcpcb *kcp, void *user) {
SOCKET sockfd = *(SOCKET *)user;
sendto(sockfd, buf, len, 0, (struct sockaddr *)&addr, sizeof(addr));
return 0;
}
std::streampos getFileSize(const std::string &filePath) {
std::ifstream file(filePath, std::ios::binary | std::ios::ate); // 以二进制模式打开并定位到文件末尾
if (!file.is_open()) {
std::cerr << "Could not open the file!" << std::endl;
return -1;
}
std::streampos fileSize = file.tellg(); // 获取文件大小
file.close();
return fileSize;
}
void replaceUsingRegex(std::string &str, const std::string &pattern, const std::string &replacement) {
std::regex re(pattern);
str = std::regex_replace(str, re, replacement);
}
int main()
{
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);
std::string hostUrl;
std::cout << "请输入服务器IP" << std::endl;
std::cin >> hostUrl;
addr.sin_family = AF_INET;
addr.sin_port = htons(666); // 服务器端口
addr.sin_addr.s_addr = inet_addr(hostUrl.data()); // 服务器地址
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
ikcpcb kcp = ikcp_create(123, (void)&sockfd);
kcp->output = udp_send;
ikcp_nodelay(kcp, 2, 10, 2, 1);
std::string path;
char data[10240];
int len = sizeof(addr);
while (1)
{
std::cout << "请输入要上传的文件地址" << std::endl;
std::cin >> path;
std::cout << "正在上传中......" << std::endl;
replaceUsingRegex(path,"[/]","\");
//上传文件名称与文件大小
std::string name = "[begin]"+path.substr(path.find_last_of('\')+1)+"&"+std::to_string(getFileSize(path)) +"[end]";
ikcp_send(kcp, name.data(),name.length()+1);
ikcp_update(kcp, iclock());
//上传文件内容
std::ifstream inputFile(path, std::ios::binary);
while (!inputFile.eof()) { // 检查是否到达文件末尾
inputFile.read(data, 10240); // 读取指定长度的字节到缓冲区
int size = inputFile.gcount();
if (size > 0) {
ikcp_send(kcp, data, size);
}
ikcp_update(kcp, iclock());
}
auto interval=iclock();
while (iclock()- interval<22222)
{
isleep(1);
ikcp_update(kcp, iclock());
}
std::cout << "上传完毕" << std::endl;
}
return 0;
}

接收端代码
#include <stdio.h>
#include <stdlib.h>
#include "..\test.h"
#include <ikcp.h>
#include
#include <winsock.h>
#include
#include
#pragma comment(lib, "ws2_32.lib")
int sockfd;
// UDP 发送函数
int udp_send(const char *buf, int len, ikcpcb kcp, void user) {
sockaddr_in
addr = (sockaddr_in
)user;
sendto(sockfd, buf, len, 0, (struct sockaddr *)addr, sizeof(*addr));
return 0;
}
int main()
{
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);
sockaddr_in server_addr, client_addr;
// 创建 socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
// 配置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(666);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
int timeout = 44444;
int noTimeout = 0;
// 绑定 socket
bind(sockfd, (const struct sockaddr )&server_addr, sizeof(server_addr));
ikcpcb kcp = ikcp_create(123, (void)&client_addr);
kcp->output = udp_send;
ikcp_nodelay(kcp, 2, 10, 2, 1);
int clientLen = sizeof(client_addr);
char buffer[10240];
char data[10240];
std::string fileName;
unsigned int fileSize;
std::ofstream outputFile;
std::string fileStr;
char fileStrOldLen=-1;
bool flag=true;//是否处于接收文件基本信息阶段
while (1)
{
label1:
int length = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr )&client_addr, &clientLen);
if (length < 0)
{
std::cout << "网络连接断开" << std::endl;
fileStrOldLen = -1;
outputFile.close();
flag = true;
fileStr.clear();
continue;
}
ikcp_input(kcp, buffer, length);
ikcp_update(kcp, iclock());
int ret = ikcp_recv(kcp, data, sizeof(data));
if (ret > 0)
{
if (flag)
{
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char
)&timeout, sizeof(timeout));
fileStr += data;
auto beginIndex = fileStr.find("[begin]");
auto endIndex = fileStr.find("[end]");
if (beginIndex == -1 && endIndex == -1)//一次读不完的情况
{
fileStrOldLen = fileStr.length();
goto label1;
}
if (fileStrOldLen == -1)//一次读完的情况
{
if(endIndex+5== fileStr.length()) fileStrOldLen = fileStr.length();//一次读完并且没有读取到文件内容字节数据的情况
else fileStrOldLen = endIndex + 5;//一次读完并且有读取到文件内容字节数据的情况
}
auto splitIndex = fileStr.find_first_of('&');
fileName = fileStr.substr(7, splitIndex - 7);
fileSize = std::stoul(fileStr.substr(splitIndex + 1, endIndex - 1 - splitIndex));
char subtractLen = endIndex + 5 - fileStrOldLen;
if (subtractLen > 0)//还存在文件内容字节数据需要写入的情况
{
char allLen = ret - subtractLen;
beginIndex = ret - allLen;
outputFile.open(fileName, std::ios::binary);
outputFile.write(&data[beginIndex], allLen);
fileSize -= allLen;
}
fileStrOldLen = -1;
fileStr.clear();
flag = false;
std::cout << fileName + "正在上传......" << std::endl;
}
else
{
if (!outputFile.is_open()) outputFile.open(fileName, std::ios::binary);
outputFile.write(data, ret);
if ((fileSize -= ret) > 0)//接收文件内容
{
goto label1;
}
else//接收完毕
{
outputFile.close();
std::cout << fileName + "上传完毕" << std::endl;
flag = true;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char
)&noTimeout, sizeof(noTimeout));
}
}
}
}
return 0;
}

@skywind3000
Copy link
Owner

麻烦重新好好帖下代码

@HeYang6
Copy link
Author

HeYang6 commented Jun 27, 2024

麻烦重新好好帖下代码

image

image
image
image

@HeYang6
Copy link
Author

HeYang6 commented Jun 28, 2024

我已经找到原因了

@HeYang6 HeYang6 closed this as completed Jun 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants