skywind3000 / kcp

:zap: KCP - A Fast and Reliable ARQ Protocol
MIT License
15.33k stars 2.5k forks source link

ikcp_recv只有第一次能返回正确的值,其余都是返回-1 #237

Open flyerSon opened 4 years ago

flyerSon commented 4 years ago

请帮我看看哪里用错了。

这是server

include "asio.hpp"

include

include

include

include "ikcp.h"

define IPADDRESS "10.246.106.114"

define UDP_PORT 11000

using asio::ip::udp; using asio::ip::address;

uint32_t conv = 123; ikcpcb* service_kcp = NULL;

void Sender(const std::string& in) { asio::io_service io_service; udp::socket socket(io_service); udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT); socket.open(udp::v4()); std::error_code err; auto sent = socket.send_to(asio::buffer(in), remote_endpoint, 0, err); socket.close(); std::cout << "Sent Payload --- " << sent << "\n"; }

int udp_out_put(const char buf, int len, ikcpcb kcp, void* user) { std::string in(buf, len); Sender(in); return 0; }

void do_recv(char* buf, int len) { std::string in(buf, len); std::cout << "kcp recv data:" << in << std::endl; }

uint32_t update_now_time_ms() { using namespace std; auto time_now = chrono::system_clock::now(); auto duration_in_ms = chrono::duration_cast(time_now.time_since_epoch()); return duration_in_ms.count(); }

struct Service { asio::io_service io_service; udp::socket socket{ io_service }; std::array<char, 1024> recv_buffer; udp::endpoint remote_endpoint;

int count = 100000;

void handle_receive(const std::error_code& error, size_t bytes_transferred) {
    if (error) {
        std::cout << "Receive failed: " << error.message() << "\n";
        return;
    }
    std::string data(recv_buffer.begin(), recv_buffer.begin() + bytes_transferred);
    ikcp_input(service_kcp, data.c_str(), bytes_transferred);
    char kcp_buf[1000];
    memset(kcp_buf, '\0', sizeof(kcp_buf));
    int kcp_recvd_bytes = ikcp_recv(service_kcp, kcp_buf, sizeof(kcp_buf));
    if (kcp_recvd_bytes > 0)
    {
        do_recv(kcp_buf, kcp_recvd_bytes);
    }

    std::cout << "kcp_byte:" << kcp_recvd_bytes << " udp received: " << data << " (" << error.message() << ")\n";
    wait();
}

void wait() {
    socket.async_receive_from(asio::buffer(recv_buffer),
        remote_endpoint,
        bind(&Service::handle_receive, this, std::placeholders::_1, std::placeholders::_2));
}

void receiver()
{
    socket.open(udp::v4());
    socket.bind(udp::endpoint(address::from_string(IPADDRESS), UDP_PORT));

    wait();
    std::cout << "Receiving\n";
    io_service.run();
    std::cout << "Receiver exit\n";
}

};

void init_ikcp() { service_kcp = ikcp_create(conv, (void*)1); service_kcp->output = udp_out_put; ikcp_nodelay(service_kcp,1,5,1,1); }

int main(int argc, char* argv[]) {

init_ikcp();
Service service;
std::thread r([&] { service.receiver(); });

while(true)
{ 
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    ikcp_update(service_kcp, update_now_time_ms());
}

r.join();
return 1;

}


这是client

include "asio.hpp"

include

include

include

include "ikcp.h"

define IPADDRESS "10.246.106.114"

define UDP_PORT 11000

using asio::ip::udp; using asio::ip::address;

uint32_t conv = 123; ikcpcb* client_kcp = NULL;

void sender(const std::string& in) { asio::io_service io_service; udp::socket socket(io_service); udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT); socket.open(udp::v4()); std::error_code err; auto sent = socket.send_to(asio::buffer(in), remote_endpoint, 0, err); socket.close(); std::cout << "Sent Payload --- " << sent << "\n"; }

int udp_out_put(const char buf, int len, ikcpcb kcp, void* arg) { std::string in(buf, len); sender(in); return 0; }

void do_recv(char* buf, int len) { std::string in(buf, len); std::cout << "recv data:" << in << std::endl; }

void init_ikcp() { client_kcp = ikcp_create(conv,NULL); client_kcp->output = udp_out_put; //ikcp_nodelay(client_kcp,1,5,1,1); }

uint32_t update_now_time_ms() { using namespace std; auto time_now = chrono::system_clock::now(); auto duration_in_ms = chrono::duration_cast(time_now.time_since_epoch()); return duration_in_ms.count(); }

int main(int argc, char* argv[]) { std::string input = argc > 1 ? argv[1] : "hello world"; std::cout << "Input is '" << input.c_str() << "'\nSending it to Sender Function...\n";

init_ikcp();
while(true)
{ 
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    ikcp_update(client_kcp, update_now_time_ms());
    ikcp_send(client_kcp, input.c_str(), input.size());
}
return 1;

}

skywind3000 commented 4 years ago

你能不能修改下你代码的格式,看看 github 上面怎么正确的贴代码再说?

flyerSon commented 4 years ago

你能不能修改下你代码的格式,看看 github 上面怎么正确的贴代码再说?

实在抱歉,我把代码放在这个txt中,你帮忙看看,谢谢! main.txt

brother-yan-web commented 4 years ago

题主我来帮你一把

#include <asio.hpp>
#include <array>
#include <thread>
#include <iostream>
#include "ikcp.h"

#define IPADDRESS "127.0.0.1" // "192.168.1.64"
#define UDP_PORT 13253

using asio::ip::udp;
using asio::ip::address;

ikcpcb *service_kcp = NULL,*client_kcp = NULL;
uint32_t conv = 123;
int32_t count = 1000;

std::mutex mutex;

void Sender(std::string in) 
{
    asio::io_service io_service;
    udp::socket socket(io_service);
    udp::endpoint remote_endpoint = udp::endpoint(address::from_string(IPADDRESS), UDP_PORT);
    socket.open(udp::v4());

    std::error_code err;
    auto sent = socket.send_to(asio::buffer(in), remote_endpoint, 0, err);
    socket.close();
    std::cout << "Sent Payload --- " << sent << "\n";
}

struct Client 
{
    asio::io_service io_service;
    udp::socket socket{io_service};
    std::array<char, 1024> recv_buffer;
    udp::endpoint remote_endpoint;

    void handle_receive(const std::error_code& error, size_t bytes_transferred) 
    {
        if (error) 
        {
            std::cout << "Receive failed: " << error.message() << "\n";
            return;
        }
        std::cout << "Received udp data: '" << std::string(recv_buffer.begin(), recv_buffer.begin()+bytes_transferred) << "' (" << error.message() << ")\n";
        mutex.lock();
        ikcp_input(client_kcp,recv_buffer.begin(),bytes_transferred);
        char kcp_buf[1000];
        memset(kcp_buf,'\0',sizeof(kcp_buf));
        //不知为何,第一次是正确的,后面就一直返回-1,加锁也一样
        int kcp_recvd_bytes = ikcp_recv(client_kcp,kcp_buf,sizeof(kcp_buf));
        mutex.unlock();
        if(kcp_recvd_bytes > 0)
        {
            std::string data(kcp_buf,kcp_recvd_bytes);
            std::cout << "Received ikcp data:" << data << std::endl;
        }
        else 
        {
            std::cout << "Received ikcp byte:" << kcp_recvd_bytes << std::endl;
        }

        if (--count > 0) 
        {
            std::cout << "Count: " << count << "\n";
            wait();
        }
    }

    void wait() 
    {
        socket.async_receive_from(asio::buffer(recv_buffer),
            remote_endpoint,
            bind(&Client::handle_receive, this, std::placeholders::_1, std::placeholders::_2));
    }

    void Receiver()
    {
        socket.open(udp::v4());
        socket.bind(udp::endpoint(address::from_string(IPADDRESS), UDP_PORT));

        wait();

        std::cout << "Receiving\n";
        io_service.run();
        std::cout << "Receiver exit\n";
    }
};

int udp_out_put(const char *buf,int len,ikcpcb *kcp,void *user)
{
    std::string in(buf,len);
    Sender(in);
    return 0;
}

void init_ikcp()
{
    service_kcp = ikcp_create(conv,(void*)0);
    service_kcp->output = udp_out_put;

    client_kcp = ikcp_create(conv,(void*)1);
    client_kcp->output = udp_out_put;
}

uint32_t update_now_time_ms()
{
    using namespace std;
    auto time_now = chrono::system_clock::now();
    auto duration_in_ms = chrono::duration_cast<chrono::milliseconds>(time_now.time_since_epoch());
    return duration_in_ms.count();
}

int main(int argc, char *argv[])
{
    init_ikcp();

    Client client;
    std::thread r([&] { client.Receiver(); });

    std::string input = argc>1? argv[1] : "hello world";
    std::cout << "Input is '" << input.c_str() << "'\nSending it to Sender Function...\n";

    for (int i = 0; i < count; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        ikcp_update(service_kcp,update_now_time_ms());
        mutex.lock();
        ikcp_update(client_kcp,update_now_time_ms());
        mutex.unlock();
        ikcp_send(service_kcp,input.c_str(),input.size());
    }

    r.join();
}