1. 调整日志掩码的表示形式:10进制改为16进制

2. 增加打开所有日志的宏:IKCP_LOG_ALL
This commit is contained in:
wang_hongqi 2022-11-16 09:54:00 +00:00
parent f553df7afc
commit ca79d08376
3 changed files with 582 additions and 214 deletions

119
ikcp.h
View File

@ -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
View 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());
// 每隔 20mskcp1发送数据
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
View 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;
}