mirror of
https://github.com/skywind3000/kcp.git
synced 2025-03-22 07:22:59 +08:00
1. 调整日志掩码的表示形式:10进制改为16进制
2. 增加打开所有日志的宏:IKCP_LOG_ALL
This commit is contained in:
parent
f553df7afc
commit
ca79d08376
119
ikcp.h
119
ikcp.h
@ -22,13 +22,13 @@
|
|||||||
//=====================================================================
|
//=====================================================================
|
||||||
#ifndef __INTEGER_32_BITS__
|
#ifndef __INTEGER_32_BITS__
|
||||||
#define __INTEGER_32_BITS__
|
#define __INTEGER_32_BITS__
|
||||||
#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \
|
#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) \
|
||||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \
|
|| defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) \
|
||||||
defined(_M_AMD64)
|
|| defined(_M_AMD64)
|
||||||
typedef unsigned int ISTDUINT32;
|
typedef unsigned int ISTDUINT32;
|
||||||
typedef int ISTDINT32;
|
typedef int ISTDINT32;
|
||||||
#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \
|
#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) \
|
||||||
defined(__i386) || defined(_M_X86)
|
|| defined(__i386) || defined(_M_X86)
|
||||||
typedef unsigned long ISTDUINT32;
|
typedef unsigned long ISTDUINT32;
|
||||||
typedef long ISTDINT32;
|
typedef long ISTDINT32;
|
||||||
#elif defined(__MACOS__)
|
#elif defined(__MACOS__)
|
||||||
@ -134,7 +134,8 @@ typedef unsigned long long IUINT64;
|
|||||||
#ifndef __IQUEUE_DEF__
|
#ifndef __IQUEUE_DEF__
|
||||||
#define __IQUEUE_DEF__
|
#define __IQUEUE_DEF__
|
||||||
|
|
||||||
struct IQUEUEHEAD {
|
struct IQUEUEHEAD
|
||||||
|
{
|
||||||
struct IQUEUEHEAD *next, *prev;
|
struct IQUEUEHEAD *next, *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,17 +145,18 @@ typedef struct IQUEUEHEAD iqueue_head;
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// queue init
|
// queue init
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
#define IQUEUE_HEAD_INIT(name) { &(name), &(name) }
|
#define IQUEUE_HEAD_INIT(name) \
|
||||||
#define IQUEUE_HEAD(name) \
|
{ \
|
||||||
struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
|
&(name), &(name) \
|
||||||
|
}
|
||||||
|
#define IQUEUE_HEAD(name) struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
|
||||||
|
|
||||||
#define IQUEUE_INIT(ptr) ( \
|
#define IQUEUE_INIT(ptr) ((ptr)->next = (ptr), (ptr)->prev = (ptr))
|
||||||
(ptr)->next = (ptr), (ptr)->prev = (ptr))
|
|
||||||
|
|
||||||
#define IOFFSETOF(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
|
#define IOFFSETOF(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
|
||||||
|
|
||||||
#define ICONTAINEROF(ptr, type, member) ( \
|
#define ICONTAINEROF(ptr, type, member) \
|
||||||
(type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )
|
((type *)(((char *)((type *)ptr)) - IOFFSETOF(type, member)))
|
||||||
|
|
||||||
#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
|
#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
|
||||||
|
|
||||||
@ -162,23 +164,26 @@ typedef struct IQUEUEHEAD iqueue_head;
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// queue operation
|
// queue operation
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
#define IQUEUE_ADD(node, head) ( \
|
#define IQUEUE_ADD(node, head) \
|
||||||
(node)->prev = (head), (node)->next = (head)->next, \
|
((node)->prev = (head), (node)->next = (head)->next, \
|
||||||
(head)->next->prev = (node), (head)->next = (node))
|
(head)->next->prev = (node), (head)->next = (node))
|
||||||
|
|
||||||
#define IQUEUE_ADD_TAIL(node, head) ( \
|
#define IQUEUE_ADD_TAIL(node, head) \
|
||||||
(node)->prev = (head)->prev, (node)->next = (head), \
|
((node)->prev = (head)->prev, (node)->next = (head), \
|
||||||
(head)->prev->next = (node), (head)->prev = (node))
|
(head)->prev->next = (node), (head)->prev = (node))
|
||||||
|
|
||||||
#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
|
#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
|
||||||
|
|
||||||
#define IQUEUE_DEL(entry) (\
|
#define IQUEUE_DEL(entry) \
|
||||||
(entry)->next->prev = (entry)->prev, \
|
((entry)->next->prev = (entry)->prev, (entry)->prev->next = (entry)->next, \
|
||||||
(entry)->prev->next = (entry)->next, \
|
|
||||||
(entry)->next = 0, (entry)->prev = 0)
|
(entry)->next = 0, (entry)->prev = 0)
|
||||||
|
|
||||||
#define IQUEUE_DEL_INIT(entry) do { \
|
#define IQUEUE_DEL_INIT(entry) \
|
||||||
IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0)
|
do \
|
||||||
|
{ \
|
||||||
|
IQUEUE_DEL(entry); \
|
||||||
|
IQUEUE_INIT(entry); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
|
#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
|
||||||
|
|
||||||
@ -202,17 +207,27 @@ typedef struct IQUEUEHEAD iqueue_head;
|
|||||||
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
|
for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next)
|
||||||
|
|
||||||
|
|
||||||
#define __iqueue_splice(list, head) do { \
|
#define __iqueue_splice(list, head) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
iqueue_head *first = (list)->next, *last = (list)->prev; \
|
iqueue_head *first = (list)->next, *last = (list)->prev; \
|
||||||
iqueue_head *at = (head)->next; \
|
iqueue_head *at = (head)->next; \
|
||||||
(first)->prev = (head), (head)->next = (first); \
|
(first)->prev = (head), (head)->next = (first); \
|
||||||
(last)->next = (at), (at)->prev = (last); } while (0)
|
(last)->next = (at), (at)->prev = (last); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define iqueue_splice(list, head) do { \
|
#define iqueue_splice(list, head) \
|
||||||
if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0)
|
do \
|
||||||
|
{ \
|
||||||
|
if (!iqueue_is_empty(list)) __iqueue_splice(list, head); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define iqueue_splice_init(list, head) do { \
|
#define iqueue_splice_init(list, head) \
|
||||||
iqueue_splice(list, head); iqueue_init(list); } while (0)
|
do \
|
||||||
|
{ \
|
||||||
|
iqueue_splice(list, head); \
|
||||||
|
iqueue_init(list); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -234,12 +249,11 @@ typedef struct IQUEUEHEAD iqueue_head;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef IWORDS_BIG_ENDIAN
|
#ifndef IWORDS_BIG_ENDIAN
|
||||||
#if defined(__hppa__) || \
|
#if defined(__hppa__) || defined(__m68k__) || defined(mc68000) \
|
||||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
|| defined(_M_M68K) || (defined(__MIPS__) && defined(__MIPSEB__)) \
|
||||||
(defined(__MIPS__) && defined(__MIPSEB__)) || \
|
|| defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) \
|
||||||
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
|
|| defined(__sparc__) || defined(__powerpc__) || defined(__mc68000__) \
|
||||||
defined(__sparc__) || defined(__powerpc__) || \
|
|| defined(__s390x__) || defined(__s390__)
|
||||||
defined(__mc68000__) || defined(__s390x__) || defined(__s390__)
|
|
||||||
#define IWORDS_BIG_ENDIAN 1
|
#define IWORDS_BIG_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -319,21 +333,27 @@ struct IKCPCB
|
|||||||
|
|
||||||
typedef struct IKCPCB ikcpcb;
|
typedef struct IKCPCB ikcpcb;
|
||||||
|
|
||||||
#define IKCP_LOG_OUTPUT 1
|
#define IKCP_LOG_OUTPUT 0x000001
|
||||||
#define IKCP_LOG_INPUT 2
|
#define IKCP_LOG_INPUT 0x000002
|
||||||
#define IKCP_LOG_SEND 4
|
#define IKCP_LOG_SEND 0x000004
|
||||||
#define IKCP_LOG_RECV 8
|
#define IKCP_LOG_RECV 0x000008
|
||||||
#define IKCP_LOG_IN_DATA 16
|
#define IKCP_LOG_IN_DATA 0x000010
|
||||||
#define IKCP_LOG_IN_ACK 32
|
#define IKCP_LOG_IN_ACK 0x000020
|
||||||
#define IKCP_LOG_IN_PROBE 64
|
#define IKCP_LOG_IN_PROBE 0x000040
|
||||||
#define IKCP_LOG_IN_WINS 128
|
#define IKCP_LOG_IN_WINS 0x000080
|
||||||
#define IKCP_LOG_OUT_DATA 256
|
#define IKCP_LOG_OUT_DATA 0x000100
|
||||||
#define IKCP_LOG_OUT_ACK 512
|
#define IKCP_LOG_OUT_ACK 0x000200
|
||||||
#define IKCP_LOG_OUT_PROBE 1024
|
#define IKCP_LOG_OUT_PROBE 0x000400
|
||||||
#define IKCP_LOG_OUT_WINS 2048
|
#define IKCP_LOG_OUT_WINS 0x000800
|
||||||
|
#define IKCP_LOG_ALL \
|
||||||
|
(IKCP_LOG_OUTPUT | IKCP_LOG_INPUT | IKCP_LOG_SEND | IKCP_LOG_RECV \
|
||||||
|
| IKCP_LOG_IN_DATA | IKCP_LOG_IN_ACK | IKCP_LOG_IN_PROBE \
|
||||||
|
| IKCP_LOG_IN_WINS | IKCP_LOG_OUT_DATA | IKCP_LOG_OUT_ACK \
|
||||||
|
| IKCP_LOG_OUT_PROBE | IKCP_LOG_OUT_WINS)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
@ -395,7 +415,8 @@ int ikcp_waitsnd(const ikcpcb *kcp);
|
|||||||
// interval: internal update timer interval in millisec, default is 100ms
|
// interval: internal update timer interval in millisec, default is 100ms
|
||||||
// resend: 0:disable fast resend(default), 1:enable fast resend
|
// resend: 0:disable fast resend(default), 1:enable fast resend
|
||||||
// nc: 0:normal congestion control(default), 1:disable congestion control
|
// nc: 0:normal congestion control(default), 1:disable congestion control
|
||||||
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc);
|
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend,
|
||||||
|
int nc);
|
||||||
|
|
||||||
|
|
||||||
void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
|
void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
|
||||||
@ -412,5 +433,3 @@ IUINT32 ikcp_getconv(const void *ptr);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
183
test_client.c
Normal file
183
test_client.c
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include "ikcp.c"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int socket;
|
||||||
|
struct sockaddr_in server_sa;
|
||||||
|
int channel;
|
||||||
|
} test_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
kcp_output(const char *buf, int len, ikcpcb *kcp, void *user)
|
||||||
|
{
|
||||||
|
test_ctx_t *ctx = (test_ctx_t *)user;
|
||||||
|
|
||||||
|
sendto(ctx->socket, buf, len, 0, (struct sockaddr *)&ctx->server_sa,
|
||||||
|
sizeof(ctx->server_sa));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_ctx_t ctx;
|
||||||
|
char *server_addr = "127.0.0.1";
|
||||||
|
int server_port = 50000;
|
||||||
|
int channel;
|
||||||
|
|
||||||
|
switch (argc)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
server_port = atoi(argv[3]);
|
||||||
|
if (server_port <= 0 || 65535 < server_port)
|
||||||
|
{
|
||||||
|
printf("invalid port: %s\n", argv[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case 3: server_addr = argv[2];
|
||||||
|
case 2:
|
||||||
|
channel = atoi(argv[1]);
|
||||||
|
if (channel <= 0)
|
||||||
|
{
|
||||||
|
printf("invalid channel number: %s\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s <channel> [server_ip] [server_port]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init ctx
|
||||||
|
bzero(&ctx, sizeof(ctx));
|
||||||
|
|
||||||
|
ctx.channel = channel;
|
||||||
|
|
||||||
|
ctx.server_sa.sin_family = AF_INET;
|
||||||
|
ctx.server_sa.sin_port = htons(server_port);
|
||||||
|
if (inet_pton(AF_INET, server_addr, &ctx.server_sa.sin_addr) < 0)
|
||||||
|
{
|
||||||
|
printf("invalid server address: %s\n", server_addr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create udp
|
||||||
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) return 1;
|
||||||
|
|
||||||
|
int nb;
|
||||||
|
nb = 1;
|
||||||
|
ioctl(s, FIONBIO, &nb);
|
||||||
|
|
||||||
|
ctx.socket = s;
|
||||||
|
|
||||||
|
ikcpcb *kcp;
|
||||||
|
|
||||||
|
kcp = ikcp_create(ctx.channel, &ctx);
|
||||||
|
if (kcp == NULL) return 1;
|
||||||
|
|
||||||
|
ikcp_setoutput(kcp, kcp_output);
|
||||||
|
ikcp_nodelay(kcp, 1, 1, 2, 1);
|
||||||
|
ikcp_wndsize(kcp, 1024, 1024);
|
||||||
|
|
||||||
|
IUINT32 current = iclock();
|
||||||
|
IUINT32 slap = current + 20;
|
||||||
|
IUINT32 index = 0;
|
||||||
|
IUINT32 next = 0;
|
||||||
|
ssize_t n;
|
||||||
|
char buffer[65536];
|
||||||
|
IINT64 sumrtt = 0;
|
||||||
|
int count = 0;
|
||||||
|
int maxrtt = 0;
|
||||||
|
IUINT32 ts1 = iclock();
|
||||||
|
|
||||||
|
printf("inited\n");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
isleep(1);
|
||||||
|
current = iclock();
|
||||||
|
ikcp_update(kcp, iclock());
|
||||||
|
|
||||||
|
// 每隔 20ms,kcp1发送数据
|
||||||
|
for (; current >= slap; slap += 20)
|
||||||
|
{
|
||||||
|
((IUINT32 *)buffer)[0] = index++;
|
||||||
|
((IUINT32 *)buffer)[1] = current;
|
||||||
|
|
||||||
|
// 发送上层协议包
|
||||||
|
ikcp_send(kcp, buffer, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理底层数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
n = recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL);
|
||||||
|
if (n < 0) break;
|
||||||
|
|
||||||
|
ikcp_input(kcp, buffer, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// kcp收到应用据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
n = ikcp_recv(kcp, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
// 没有收到包就退出
|
||||||
|
if (n < 0) break;
|
||||||
|
|
||||||
|
char *p = buffer;
|
||||||
|
char *last = p + n;
|
||||||
|
while (p + 8 <= last)
|
||||||
|
{
|
||||||
|
IUINT32 sn = *(IUINT32 *)(p + 0);
|
||||||
|
IUINT32 ts = *(IUINT32 *)(p + 4);
|
||||||
|
IUINT32 rtt = current - ts;
|
||||||
|
|
||||||
|
if (sn != next)
|
||||||
|
{
|
||||||
|
// 如果收到的包不连续
|
||||||
|
printf("ERROR sn %d<->%d\n", (int)count, (int)next);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 8;
|
||||||
|
next++;
|
||||||
|
sumrtt += rtt;
|
||||||
|
count++;
|
||||||
|
if (rtt > (IUINT32)maxrtt) maxrtt = rtt;
|
||||||
|
|
||||||
|
printf("[RECV] sn=%d rtt=%d\n", (int)sn, (int)rtt);
|
||||||
|
|
||||||
|
if (next > 1000) goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != last)
|
||||||
|
{
|
||||||
|
// 收到不完整的包
|
||||||
|
printf("receiving a incomplete package\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
ts1 = iclock() - ts1;
|
||||||
|
|
||||||
|
ikcp_release(kcp);
|
||||||
|
|
||||||
|
printf("result (%dms):\n", (int)ts1);
|
||||||
|
printf("avgrtt=%d maxrtt=%d\n", (int)(sumrtt / count), (int)maxrtt);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
166
test_server.c
Normal file
166
test_server.c
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include "ikcp.c"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int socket;
|
||||||
|
struct sockaddr_in sa;
|
||||||
|
struct sockaddr_in peer_sa;
|
||||||
|
socklen_t peer_len;
|
||||||
|
int channel;
|
||||||
|
} test_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
kcp_output(const char *buf, int len, ikcpcb *kcp, void *user)
|
||||||
|
{
|
||||||
|
test_ctx_t *ctx = (test_ctx_t *)user;
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t n = sendto(ctx->socket, buf, len, 0,
|
||||||
|
(struct sockaddr *)&ctx->peer_sa, sizeof(ctx->peer_sa));
|
||||||
|
|
||||||
|
printf("output: %d/%d bytes\n", n, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_ctx_t ctx;
|
||||||
|
char *listen_addr = "127.0.0.1";
|
||||||
|
int listen_port = 50001;
|
||||||
|
int channel;
|
||||||
|
|
||||||
|
switch (argc)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
listen_port = atoi(argv[3]);
|
||||||
|
if (listen_port <= 0 || 65535 < listen_port)
|
||||||
|
{
|
||||||
|
printf("invalid port: %s\n", argv[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case 3: listen_addr = argv[2];
|
||||||
|
case 2:
|
||||||
|
channel = atoi(argv[1]);
|
||||||
|
if (channel <= 0)
|
||||||
|
{
|
||||||
|
printf("invalid channel number: %s\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s <channel> [listen_ip] [listen_port]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init ctx
|
||||||
|
bzero(&ctx, sizeof(ctx));
|
||||||
|
|
||||||
|
ctx.channel = channel;
|
||||||
|
|
||||||
|
ctx.sa.sin_family = AF_INET;
|
||||||
|
ctx.sa.sin_port = htons(listen_port);
|
||||||
|
if (inet_pton(AF_INET, listen_addr, &ctx.sa.sin_addr) < 0)
|
||||||
|
{
|
||||||
|
printf("invalid server address: %s\n", listen_addr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create udp
|
||||||
|
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s == -1) return 1;
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&ctx.sa, sizeof(ctx.sa)) == -1)
|
||||||
|
{
|
||||||
|
printf("bind failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nb;
|
||||||
|
nb = 1;
|
||||||
|
ioctl(s, FIONBIO, &nb);
|
||||||
|
|
||||||
|
ctx.socket = s;
|
||||||
|
|
||||||
|
ikcpcb *kcp;
|
||||||
|
|
||||||
|
kcp = ikcp_create(ctx.channel, &ctx);
|
||||||
|
if (kcp == NULL) return 1;
|
||||||
|
|
||||||
|
ikcp_setoutput(kcp, kcp_output);
|
||||||
|
ikcp_nodelay(kcp, 1, 1, 2, 1);
|
||||||
|
ikcp_wndsize(kcp, 1024, 1024);
|
||||||
|
|
||||||
|
IUINT32 current = iclock();
|
||||||
|
IUINT32 slap = current + 20;
|
||||||
|
IUINT32 index = 0;
|
||||||
|
IUINT32 next = 0;
|
||||||
|
ssize_t n;
|
||||||
|
char buffer[65536];
|
||||||
|
|
||||||
|
printf("inited\n");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
isleep(1);
|
||||||
|
current = iclock();
|
||||||
|
ikcp_update(kcp, iclock());
|
||||||
|
|
||||||
|
// 处理底层数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bzero(&ctx.peer_sa.sin_addr, sizeof(ctx.peer_sa.sin_addr));
|
||||||
|
ctx.peer_len = sizeof(ctx.peer_sa);
|
||||||
|
|
||||||
|
n = recvfrom(s, buffer, sizeof(buffer), 0,
|
||||||
|
(struct sockaddr *)&ctx.peer_sa, &ctx.peer_len);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
{
|
||||||
|
printf("recvfrom error: %d\n", n);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ip[INET_ADDRSTRLEN] = {0};
|
||||||
|
inet_ntop(ctx.peer_sa.sin_family, &ctx.peer_sa.sin_addr, ip,
|
||||||
|
INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
printf("recv: %d bytes from %s:%d\n", n, ip,
|
||||||
|
ntohs(ctx.peer_sa.sin_port));
|
||||||
|
|
||||||
|
ikcp_input(kcp, buffer, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// kcp回显数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
n = ikcp_recv(kcp, buffer, 10);
|
||||||
|
|
||||||
|
// 没有收到包就退出
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ikcp_send(kcp, buffer, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ikcp_release(kcp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user