mirror of
https://github.com/beykery/cocosocket.git
synced 2026-09-03 06:15:40 +08:00
oschina上copy
This commit is contained in:
@@ -1 +1 @@
|
||||
5;0;-1
|
||||
5;0;6;-1
|
||||
Binary file not shown.
BIN
cocosocket4unity/Library/AssetVersioning.db
Normal file
BIN
cocosocket4unity/Library/AssetVersioning.db
Normal file
Binary file not shown.
Binary file not shown.
1
cocosocket4unity/Library/LastSceneManagerSetup.txt
Normal file
1
cocosocket4unity/Library/LastSceneManagerSetup.txt
Normal file
@@ -0,0 +1 @@
|
||||
sceneSetups: []
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
0000.5787632e.0000
|
||||
0000.57876340.0000
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
cocosocket4unity/ProjectSettings/ClusterInputManager.asset
Normal file
BIN
cocosocket4unity/ProjectSettings/ClusterInputManager.asset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
m_EditorVersion: 5.2.4f1
|
||||
m_EditorVersion: 5.3.6f1
|
||||
m_StandardAssetsVersion: 0
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,6 @@ namespace cocosocket4unity
|
||||
{
|
||||
public class ByteBuf
|
||||
{
|
||||
private int len;
|
||||
private byte[] data;
|
||||
private int readerIndex;
|
||||
private int writerIndex;
|
||||
@@ -20,8 +19,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf (int capacity)
|
||||
{
|
||||
this.len = capacity;
|
||||
this.data = new byte[len];
|
||||
this.data = new byte[capacity];
|
||||
readerIndex = 0;
|
||||
writerIndex = 0;
|
||||
markReader = 0;
|
||||
@@ -29,19 +27,22 @@ namespace cocosocket4unity
|
||||
}
|
||||
public ByteBuf(byte[] content)
|
||||
{
|
||||
this.len = content.Length;
|
||||
this.data = content;
|
||||
readerIndex = 0;
|
||||
writerIndex = len;
|
||||
writerIndex = content.Length;
|
||||
markReader = 0;
|
||||
markWriter = 0;
|
||||
}
|
||||
private ByteBuf()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* 容量
|
||||
**/
|
||||
public int Capacity ()
|
||||
{
|
||||
return len;
|
||||
return data.Length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,11 +50,11 @@ namespace cocosocket4unity
|
||||
*/
|
||||
public ByteBuf Capacity (int nc)
|
||||
{
|
||||
if (nc > len) {
|
||||
if (nc > data.Length)
|
||||
{
|
||||
byte[] old = data;
|
||||
data = new byte[nc];
|
||||
Array.Copy (old, data, len);
|
||||
len = nc;
|
||||
Array.Copy (old, data, data.Length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -75,20 +76,34 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf Copy()
|
||||
{
|
||||
ByteBuf item = new ByteBuf(len);
|
||||
Array.Copy (this.data, item.data, len);
|
||||
ByteBuf item = new ByteBuf(data.Length);
|
||||
Array.Copy (this.data, item.data, data.Length);
|
||||
item.readerIndex = readerIndex;
|
||||
item.writerIndex = writerIndex;
|
||||
item.markReader = markReader;
|
||||
item.markWriter = markWriter;
|
||||
return item;
|
||||
}
|
||||
/// <summary>
|
||||
/// 浅拷贝
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ByteBuf Duplicate()
|
||||
{
|
||||
ByteBuf item = new ByteBuf();
|
||||
item.readerIndex = readerIndex;
|
||||
item.writerIndex = writerIndex;
|
||||
item.markReader = markReader;
|
||||
item.markWriter = markWriter;
|
||||
item.data = data;
|
||||
return item;
|
||||
}
|
||||
/**
|
||||
* 获取一个字节
|
||||
**/
|
||||
public byte GetByte(int index)
|
||||
{
|
||||
if (index < len)
|
||||
if (index < data.Length)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
@@ -99,7 +114,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public int GetInt(int index)
|
||||
{
|
||||
if (index + 3 < len)
|
||||
if (index + 3 < data.Length)
|
||||
{
|
||||
int ret = ((int) data[index]) << 24;
|
||||
ret |= ((int) data[index + 1]) << 16;
|
||||
@@ -114,7 +129,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public short GetShort(int index)
|
||||
{
|
||||
if (index + 1 < len)
|
||||
if (index + 1 < data.Length)
|
||||
{
|
||||
short r1 = (short)(data[index] << 8);
|
||||
short r2 = (short)(data[index + 1]);
|
||||
@@ -144,7 +159,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public int MaxWritableBytes()
|
||||
{
|
||||
return len - writerIndex;
|
||||
return data.Length - writerIndex;
|
||||
}
|
||||
/**
|
||||
* 读取一个字节
|
||||
@@ -165,14 +180,11 @@ namespace cocosocket4unity
|
||||
{
|
||||
if (readerIndex + 3 < writerIndex)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int ret = (int)(((data [readerIndex++]) << 24) & 0xff000000);
|
||||
ret |= (((data [readerIndex++]) << 16) & 0x00ff0000);
|
||||
ret |= (((data [readerIndex++]) << 8) & 0x0000ff00);
|
||||
ret |= (((data [readerIndex++])) & 0x000000ff);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -242,7 +254,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf SetByte(int index, byte value)
|
||||
{
|
||||
if (index < len)
|
||||
if (index < data.Length)
|
||||
{
|
||||
data[index] = value;
|
||||
}
|
||||
@@ -266,7 +278,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf SetIndex(int readerIndex, int writerIndex)
|
||||
{
|
||||
if (readerIndex >= 0 && readerIndex <= writerIndex && writerIndex <= len)
|
||||
if (readerIndex >= 0 && readerIndex <= writerIndex && writerIndex <= data.Length)
|
||||
{
|
||||
this.readerIndex = readerIndex;
|
||||
this.writerIndex = writerIndex;
|
||||
@@ -278,7 +290,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf SetInt(int index, int value)
|
||||
{
|
||||
if (index + 4 <= len)
|
||||
if (index + 4 <= data.Length)
|
||||
{
|
||||
data[index++] = (byte)((value >> 24) & 0xff);
|
||||
data[index++] = (byte)((value >> 16) & 0xff);
|
||||
@@ -292,7 +304,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf SetShort(int index, short value)
|
||||
{
|
||||
if (index + 2 <= len)
|
||||
if (index + 2 <= data.Length)
|
||||
{
|
||||
data[index++] = (byte)((value >> 8) & 0xff);
|
||||
data[index++] = (byte)(value & 0xff);
|
||||
@@ -315,7 +327,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public int WritableBytes()
|
||||
{
|
||||
return len - writerIndex;
|
||||
return data.Length - writerIndex;
|
||||
}
|
||||
/**
|
||||
* 写入一个字节
|
||||
@@ -444,7 +456,7 @@ namespace cocosocket4unity
|
||||
**/
|
||||
public ByteBuf WriterIndex(int writerIndex)
|
||||
{
|
||||
if (writerIndex >= readerIndex && writerIndex <= len)
|
||||
if (writerIndex >= readerIndex && writerIndex <= data.Length)
|
||||
{
|
||||
this.writerIndex = writerIndex;
|
||||
}
|
||||
@@ -459,11 +471,6 @@ namespace cocosocket4unity
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ public class Kcp
|
||||
private ByteBuf buffer;
|
||||
private int fastresend;
|
||||
private int nocwnd;
|
||||
private bool stream;
|
||||
private int logmask;
|
||||
private Output output;
|
||||
private Object user;
|
||||
@@ -96,22 +97,25 @@ public class Kcp
|
||||
class Segment
|
||||
{
|
||||
|
||||
public int conv = 0;
|
||||
public byte cmd = 0;
|
||||
public int frg = 0;
|
||||
public int wnd = 0;
|
||||
public int ts = 0;
|
||||
public int sn = 0;
|
||||
public int una = 0;
|
||||
public int resendts = 0;
|
||||
public int rto = 0;
|
||||
public int fastack = 0;
|
||||
public int xmit = 0;
|
||||
public ByteBuf data;
|
||||
public int conv = 0;
|
||||
public byte cmd = 0;
|
||||
public int frg = 0;
|
||||
public int wnd = 0;
|
||||
public int ts = 0;
|
||||
public int sn = 0;
|
||||
public int una = 0;
|
||||
public int resendts = 0;
|
||||
public int rto = 0;
|
||||
public int fastack = 0;
|
||||
public int xmit = 0;
|
||||
public ByteBuf data;
|
||||
|
||||
public Segment(int size)
|
||||
{
|
||||
this.data = new ByteBuf(size);
|
||||
if (size > 0)
|
||||
{
|
||||
this.data = new ByteBuf(size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +135,7 @@ public class Kcp
|
||||
buf.WriteInt(ts);
|
||||
buf.WriteInt(sn);
|
||||
buf.WriteInt(una);
|
||||
buf.WriteInt(data.ReadableBytes());
|
||||
buf.WriteInt(data == null ? 0 : data.ReadableBytes());
|
||||
return buf.WriterIndex() - off;
|
||||
}
|
||||
}
|
||||
@@ -153,10 +157,11 @@ public class Kcp
|
||||
mss = mtu - IKCP_OVERHEAD;
|
||||
rx_rto = IKCP_RTO_DEF;
|
||||
rx_minrto = IKCP_RTO_MIN;
|
||||
this.interval = IKCP_INTERVAL;
|
||||
interval = IKCP_INTERVAL;
|
||||
ts_flush = IKCP_INTERVAL;
|
||||
ssthresh = IKCP_THRESH_INIT;
|
||||
dead_link = IKCP_DEADLINK;
|
||||
rcv_nxt = 0;
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
this.output = output;
|
||||
this.user = user;
|
||||
@@ -174,7 +179,7 @@ public class Kcp
|
||||
return -1;
|
||||
}
|
||||
Segment seq = rcv_queue.First();
|
||||
if (0 == seq.frg)
|
||||
if (seq.frg == 0)
|
||||
{
|
||||
return seq.data.ReadableBytes();
|
||||
}
|
||||
@@ -187,7 +192,7 @@ public class Kcp
|
||||
{
|
||||
Segment item = rcv_queue[i];
|
||||
length += item.data.ReadableBytes();
|
||||
if (0 == item.frg)
|
||||
if (item.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -208,42 +213,33 @@ public class Kcp
|
||||
return -1;
|
||||
}
|
||||
int peekSize = PeekSize();
|
||||
if (0 > peekSize)
|
||||
if (peekSize < 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
if (peekSize > buffer.WritableBytes())
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
bool fast_recover = false;
|
||||
if (rcv_queue.Count >= rcv_wnd)
|
||||
{
|
||||
fast_recover = true;
|
||||
}
|
||||
bool recover = rcv_queue.Count >= rcv_wnd;
|
||||
// merge fragment.
|
||||
int count = 0;
|
||||
int n = 0;
|
||||
for(int i=0;i<rcv_queue.Count;i++)
|
||||
int c = 0;
|
||||
int len = 0;
|
||||
for (int i=0;i<rcv_queue.Count;i++ )
|
||||
{
|
||||
Segment seg=rcv_queue[i];
|
||||
n += seg.data.ReadableBytes();
|
||||
len += seg.data.ReadableBytes();
|
||||
buffer.WriteBytes(seg.data);
|
||||
count++;
|
||||
if (0 == seg.frg)
|
||||
c++;
|
||||
if (seg.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 < count)
|
||||
if(c>0)
|
||||
rcv_queue.RemoveRange(0,c);
|
||||
if (len != peekSize)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
rcv_queue.RemoveAt(0);
|
||||
}
|
||||
throw new Exception("数据异常.");
|
||||
}
|
||||
// move available data from rcv_buf -> rcv_queue
|
||||
count = 0;
|
||||
c = 0;
|
||||
for (int i = 0; i < rcv_buf.Count;i++ )
|
||||
{
|
||||
Segment seg = rcv_buf[i];
|
||||
@@ -251,28 +247,23 @@ public class Kcp
|
||||
{
|
||||
rcv_queue.Add(seg);
|
||||
rcv_nxt++;
|
||||
count++;
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 < count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
rcv_buf.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
if(c>0)
|
||||
rcv_buf.RemoveRange(0, c);
|
||||
// fast recover
|
||||
if (rcv_queue.Count < rcv_wnd && fast_recover)
|
||||
if (rcv_queue.Count < rcv_wnd && recover)
|
||||
{
|
||||
// ready to send back IKCP_CMD_WINS in ikcp_flush
|
||||
// tell remote my window size
|
||||
probe |= IKCP_ASK_TELL;
|
||||
}
|
||||
return n;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,39 +274,48 @@ public class Kcp
|
||||
*/
|
||||
public int Send(ByteBuf buffer)
|
||||
{
|
||||
if (0 == buffer.ReadableBytes())
|
||||
if (buffer.ReadableBytes()==0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// append to previous segment in streaming mode (if possible)
|
||||
if (this.stream && this.snd_queue.Count>0)
|
||||
{
|
||||
Segment seg = snd_queue.Last();
|
||||
if (seg.data != null && seg.data.ReadableBytes() < mss)
|
||||
{
|
||||
int capacity = mss - seg.data.ReadableBytes();
|
||||
int extend = (buffer.ReadableBytes() < capacity) ? buffer.ReadableBytes() : capacity;
|
||||
seg.data.WriteBytes(buffer, extend);
|
||||
if (buffer.ReadableBytes() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
int count;
|
||||
if (buffer.ReadableBytes() < mss)
|
||||
if (buffer.ReadableBytes() <= mss)
|
||||
{
|
||||
count = 1;
|
||||
} else
|
||||
{
|
||||
count = (buffer.ReadableBytes() + mss - 1) / mss;
|
||||
}
|
||||
if (255 < count)
|
||||
if (count > 255)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
if (0 == count)
|
||||
if (count == 0)
|
||||
{
|
||||
count = 1;
|
||||
}
|
||||
//fragment
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int size;
|
||||
if (buffer.ReadableBytes() > mss)
|
||||
{
|
||||
size = mss;
|
||||
} else
|
||||
{
|
||||
size = buffer.ReadableBytes();
|
||||
}
|
||||
int size = buffer.ReadableBytes() > mss ? mss : buffer.ReadableBytes();
|
||||
Segment seg = new Segment(size);
|
||||
seg.data.WriteBytes(buffer, size);
|
||||
seg.frg = count - i - 1;
|
||||
seg.frg = this.stream?0:count - i - 1;
|
||||
snd_queue.Add(seg);
|
||||
}
|
||||
return 0;
|
||||
@@ -326,16 +326,16 @@ public class Kcp
|
||||
*
|
||||
* @param rtt
|
||||
*/
|
||||
private void update_ack(int rtt)
|
||||
private void Update_ack(int rtt)
|
||||
{
|
||||
if (0 == rx_srtt)
|
||||
if (rx_srtt == 0)
|
||||
{
|
||||
rx_srtt = rtt;
|
||||
rx_rttval = rtt / 2;
|
||||
} else
|
||||
{
|
||||
int delta = rtt - rx_srtt;
|
||||
if (0 > delta)
|
||||
if (delta < 0)
|
||||
{
|
||||
delta = -delta;
|
||||
}
|
||||
@@ -350,70 +350,90 @@ public class Kcp
|
||||
rx_rto = _ibound_(rx_minrto, rto, IKCP_RTO_MAX);
|
||||
}
|
||||
|
||||
private void shrink_buf()
|
||||
private void Shrink_buf()
|
||||
{
|
||||
if (snd_buf.Count > 0)
|
||||
{
|
||||
snd_una = snd_buf[0].sn;
|
||||
snd_una = snd_buf.First().sn;
|
||||
} else
|
||||
{
|
||||
snd_una = snd_nxt;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse_ack(int sn)
|
||||
private void Parse_ack(int sn)
|
||||
{
|
||||
if (_itimediff(sn, snd_una) < 0 || _itimediff(sn, snd_nxt) >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
for (int i = 0; i < snd_buf.Count; i++)
|
||||
{
|
||||
Segment seg = snd_buf[i];
|
||||
if (sn == seg.sn)
|
||||
{
|
||||
snd_buf.RemoveAt(index);
|
||||
snd_buf.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
if (_itimediff(sn, seg.sn) < 0)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
seg.fastack++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse_una(int una)
|
||||
private void Parse_una(int una)
|
||||
{
|
||||
int count = 0;
|
||||
int c = 0;
|
||||
for (int i = 0; i < snd_buf.Count;i++ )
|
||||
{
|
||||
Segment seg = snd_buf[i];
|
||||
if (_itimediff(una, seg.sn) > 0)
|
||||
{
|
||||
count++;
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 < count)
|
||||
if(c>0)
|
||||
snd_buf.RemoveRange(0,c);
|
||||
}
|
||||
|
||||
private void Parse_fastack(int sn)
|
||||
{
|
||||
if (_itimediff(sn, snd_una) < 0 || _itimediff(sn, snd_nxt) >= 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
snd_buf.RemoveAt(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < snd_buf.Count;i++ )
|
||||
{
|
||||
Segment seg = snd_buf[i];
|
||||
if (_itimediff(sn, seg.sn) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (sn != seg.sn)
|
||||
{
|
||||
seg.fastack++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ack_push(int sn, int ts)
|
||||
/**
|
||||
* ack append
|
||||
*
|
||||
* @param sn
|
||||
* @param ts
|
||||
*/
|
||||
private void Ack_push(int sn, int ts)
|
||||
{
|
||||
acklist.Add(sn);
|
||||
acklist.Add(ts);
|
||||
}
|
||||
|
||||
private void parse_data(Segment newseg)
|
||||
private void Parse_data(Segment newseg)
|
||||
{
|
||||
int sn = newseg.sn;
|
||||
if (_itimediff(sn, rcv_nxt + rcv_wnd) >= 0 || _itimediff(sn, rcv_nxt) < 0)
|
||||
@@ -421,7 +441,7 @@ public class Kcp
|
||||
return;
|
||||
}
|
||||
int n = rcv_buf.Count - 1;
|
||||
int after_idx = -1;
|
||||
int temp = -1;
|
||||
bool repeat = false;
|
||||
for (int i = n; i >= 0; i--)
|
||||
{
|
||||
@@ -433,42 +453,39 @@ public class Kcp
|
||||
}
|
||||
if (_itimediff(sn, seg.sn) > 0)
|
||||
{
|
||||
after_idx = i;
|
||||
temp = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!repeat)
|
||||
{
|
||||
if (after_idx == -1)
|
||||
if (temp == -1)
|
||||
{
|
||||
rcv_buf.Insert(0,newseg);
|
||||
} else
|
||||
{
|
||||
rcv_buf.Insert(after_idx + 1, newseg);
|
||||
rcv_buf.Insert(temp + 1, newseg);
|
||||
}
|
||||
}
|
||||
// move available data from rcv_buf -> rcv_queue
|
||||
int count = 0;
|
||||
for (int i = 0; i < rcv_buf.Count; i++)
|
||||
int c = 0;
|
||||
for (int i = 0; i < rcv_buf.Count;i++ )
|
||||
{
|
||||
Segment seg = rcv_buf[i];
|
||||
if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd)
|
||||
{
|
||||
rcv_queue.Add(seg);
|
||||
rcv_nxt++;
|
||||
count++;
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 < count)
|
||||
if (c>0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
rcv_buf.RemoveAt(0);
|
||||
}
|
||||
rcv_buf.RemoveRange(0, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,17 +498,18 @@ public class Kcp
|
||||
*/
|
||||
public int Input(ByteBuf data)
|
||||
{
|
||||
int s_una = snd_una;
|
||||
if (data==null||data.ReadableBytes() < IKCP_OVERHEAD)
|
||||
int una_temp = snd_una;
|
||||
int flag = 0, maxack = 0;
|
||||
if (data == null || data.ReadableBytes() < IKCP_OVERHEAD)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int offset = 0;
|
||||
while (true)
|
||||
{
|
||||
bool readed = false;
|
||||
int ts;
|
||||
int sn;
|
||||
int length;
|
||||
int len;
|
||||
int una;
|
||||
int conv_;
|
||||
int wnd;
|
||||
@@ -502,26 +520,18 @@ public class Kcp
|
||||
break;
|
||||
}
|
||||
conv_ = data.ReadInt();
|
||||
offset += 4;
|
||||
if (conv != conv_)
|
||||
if (this.conv != conv_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
cmd = data.ReadByte();
|
||||
offset += 1;
|
||||
frg = data.ReadByte();
|
||||
offset += 1;
|
||||
wnd = data.ReadShort();
|
||||
offset += 2;
|
||||
ts = data.ReadInt();
|
||||
offset += 4;
|
||||
sn = data.ReadInt();
|
||||
offset += 4;
|
||||
una = data.ReadInt();
|
||||
offset += 4;
|
||||
length = data.ReadInt();
|
||||
offset += 4;
|
||||
if (data.ReadableBytes() < length)
|
||||
len = data.ReadInt();
|
||||
if (data.ReadableBytes() < len)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
@@ -536,38 +546,48 @@ public class Kcp
|
||||
return -3;
|
||||
}
|
||||
rmt_wnd = wnd & 0x0000ffff;
|
||||
parse_una(una);
|
||||
shrink_buf();
|
||||
Parse_una(una);
|
||||
Shrink_buf();
|
||||
switch (cmd)
|
||||
{
|
||||
case IKCP_CMD_ACK:
|
||||
if (_itimediff(current, ts) >= 0)
|
||||
{
|
||||
update_ack(_itimediff(current, ts));
|
||||
Update_ack(_itimediff(current, ts));
|
||||
}
|
||||
Parse_ack(sn);
|
||||
Shrink_buf();
|
||||
if (flag == 0)
|
||||
{
|
||||
flag = 1;
|
||||
maxack = sn;
|
||||
} else if (_itimediff(sn, maxack) > 0)
|
||||
{
|
||||
maxack = sn;
|
||||
}
|
||||
parse_ack(sn);
|
||||
shrink_buf();
|
||||
break;
|
||||
case IKCP_CMD_PUSH:
|
||||
Console.WriteLine(sn);
|
||||
if (_itimediff(sn, rcv_nxt + rcv_wnd) < 0)
|
||||
{
|
||||
ack_push(sn, ts);
|
||||
if (_itimediff(sn, rcv_nxt) >= 0)
|
||||
{
|
||||
Segment seg = new Segment(length);
|
||||
seg.conv = conv_;
|
||||
seg.cmd = cmd;
|
||||
seg.frg = frg & 0x000000ff;
|
||||
seg.wnd = wnd;
|
||||
seg.ts = ts;
|
||||
seg.sn = sn;
|
||||
seg.una = una;
|
||||
if (length > 0)
|
||||
Ack_push(sn, ts);
|
||||
if (_itimediff(sn, rcv_nxt) >= 0)
|
||||
{
|
||||
seg.data.WriteBytes(data, length);
|
||||
Segment seg = new Segment(len);
|
||||
seg.conv = conv_;
|
||||
seg.cmd = cmd;
|
||||
seg.frg = frg & 0x000000ff;
|
||||
seg.wnd = wnd;
|
||||
seg.ts = ts;
|
||||
seg.sn = sn;
|
||||
seg.una = una;
|
||||
if (len > 0)
|
||||
{
|
||||
seg.data.WriteBytes(data, len);
|
||||
readed = true;
|
||||
}
|
||||
Parse_data(seg);
|
||||
}
|
||||
parse_data(seg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IKCP_CMD_WASK:
|
||||
@@ -575,39 +595,45 @@ public class Kcp
|
||||
// tell remote my window size
|
||||
probe |= IKCP_ASK_TELL;
|
||||
break;
|
||||
// do nothing
|
||||
case IKCP_CMD_WINS:
|
||||
// do nothing
|
||||
break;
|
||||
default:
|
||||
return -3;
|
||||
}
|
||||
offset += length;
|
||||
}
|
||||
if (_itimediff(snd_una, s_una) > 0)
|
||||
{
|
||||
if (cwnd < rmt_wnd)
|
||||
if (!readed)
|
||||
{
|
||||
int mss_ = mss;
|
||||
if (cwnd < ssthresh)
|
||||
data.SkipBytes(len);
|
||||
}
|
||||
}
|
||||
if (flag != 0)
|
||||
{
|
||||
Parse_fastack(maxack);
|
||||
}
|
||||
if (_itimediff(snd_una, una_temp) > 0)
|
||||
{
|
||||
if (this.cwnd < this.rmt_wnd)
|
||||
{
|
||||
if (this.cwnd < this.ssthresh)
|
||||
{
|
||||
cwnd++;
|
||||
incr += mss_;
|
||||
this.cwnd++;
|
||||
this.incr += mss;
|
||||
} else
|
||||
{
|
||||
if (incr < mss_)
|
||||
if (this.incr < mss)
|
||||
{
|
||||
incr = mss_;
|
||||
this.incr = mss;
|
||||
}
|
||||
incr += (mss_ * mss_) / incr + (mss_ / 16);
|
||||
if ((cwnd + 1) * mss_ <= incr)
|
||||
this.incr += (mss * mss) / this.incr + (mss / 16);
|
||||
if ((this.cwnd + 1) * mss <= this.incr)
|
||||
{
|
||||
cwnd++;
|
||||
this.cwnd++;
|
||||
}
|
||||
}
|
||||
if (cwnd > rmt_wnd)
|
||||
if (this.cwnd > this.rmt_wnd)
|
||||
{
|
||||
cwnd = rmt_wnd;
|
||||
incr = rmt_wnd * mss_;
|
||||
this.cwnd = this.rmt_wnd;
|
||||
this.incr = this.rmt_wnd * mss;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,12 +652,12 @@ public class Kcp
|
||||
/**
|
||||
* flush pending data
|
||||
*/
|
||||
private void flush()
|
||||
private void Flush()
|
||||
{
|
||||
int cur = current;
|
||||
int change = 0;
|
||||
int lost = 0;
|
||||
if (0 == updated)
|
||||
if (updated == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -641,25 +667,23 @@ public class Kcp
|
||||
seg.wnd = wnd_unused();
|
||||
seg.una = rcv_nxt;
|
||||
// flush acknowledges
|
||||
int count = acklist.Count / 2;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
int c = acklist.Count / 2;
|
||||
for (int i = 0; i < c; i++)
|
||||
{
|
||||
if (offset + IKCP_OVERHEAD > mtu)
|
||||
if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu)
|
||||
{
|
||||
this.output.output(buffer, this, user);
|
||||
offset = 0;
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
}
|
||||
seg.sn = acklist[i * 2 + 0];
|
||||
seg.ts = acklist[i * 2 + 1];
|
||||
offset += seg.Encode(buffer);
|
||||
seg.Encode(buffer);
|
||||
}
|
||||
acklist.Clear();
|
||||
// probe window size (if remote window size equals zero)
|
||||
if (0 == rmt_wnd)
|
||||
if (rmt_wnd == 0)
|
||||
{
|
||||
if (0 == probe_wait)
|
||||
if (probe_wait == 0)
|
||||
{
|
||||
probe_wait = IKCP_PROBE_INIT;
|
||||
ts_probe = current + probe_wait;
|
||||
@@ -686,68 +710,67 @@ public class Kcp
|
||||
if ((probe & IKCP_ASK_SEND) != 0)
|
||||
{
|
||||
seg.cmd = IKCP_CMD_WASK;
|
||||
if (offset + IKCP_OVERHEAD > mtu)
|
||||
if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu)
|
||||
{
|
||||
this.output.output(buffer, this, user);
|
||||
offset = 0;
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
}
|
||||
offset += seg.Encode(buffer);
|
||||
seg.Encode(buffer);
|
||||
}
|
||||
// flush window probing commands
|
||||
if ((probe & IKCP_ASK_TELL) != 0)
|
||||
{
|
||||
seg.cmd = IKCP_CMD_WINS;
|
||||
if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu)
|
||||
{
|
||||
this.output.output(buffer, this, user);
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
}
|
||||
seg.Encode(buffer);
|
||||
}
|
||||
probe = 0;
|
||||
// calculate window size
|
||||
int cwnd_ = Math.Min(snd_wnd, rmt_wnd);
|
||||
if (0 == nocwnd)
|
||||
int cwnd_temp = Math.Min(snd_wnd, rmt_wnd);
|
||||
if (nocwnd == 0)
|
||||
{
|
||||
cwnd_ = Math.Min(cwnd, cwnd_);
|
||||
cwnd_temp = Math.Min(cwnd, cwnd_temp);
|
||||
}
|
||||
count = 0;
|
||||
for(int i=0;i<snd_queue.Count;i++)
|
||||
// move data from snd_queue to snd_buf
|
||||
c = 0;
|
||||
for (int i=0;i<snd_queue.Count;i++)
|
||||
{
|
||||
if (_itimediff(snd_nxt, snd_una + cwnd_) >= 0)
|
||||
Segment item=snd_queue[i];
|
||||
if (_itimediff(snd_nxt, snd_una + cwnd_temp) >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Segment newseg = snd_queue[i];
|
||||
Segment newseg = item;
|
||||
newseg.conv = conv;
|
||||
newseg.cmd = IKCP_CMD_PUSH;
|
||||
newseg.wnd = seg.wnd;
|
||||
newseg.ts = cur;
|
||||
newseg.sn = snd_nxt;
|
||||
newseg.sn = snd_nxt++;
|
||||
newseg.una = rcv_nxt;
|
||||
newseg.resendts = cur;
|
||||
newseg.rto = rx_rto;
|
||||
newseg.fastack = 0;
|
||||
newseg.xmit = 0;
|
||||
snd_buf.Add(newseg);
|
||||
snd_nxt++;
|
||||
count++;
|
||||
c++;
|
||||
}
|
||||
if (0 < count)
|
||||
if (c > 0)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
snd_queue.RemoveAt(0);
|
||||
}
|
||||
snd_queue.RemoveRange(0,c);
|
||||
}
|
||||
// calculate resent
|
||||
int resent = fastresend;
|
||||
if (fastresend <= 0)
|
||||
{
|
||||
resent = -1;
|
||||
}
|
||||
int rtomin = rx_rto >> 3;
|
||||
if (nodelay != 0)
|
||||
{
|
||||
rtomin = 0;
|
||||
}
|
||||
int resent = (fastresend > 0) ? fastresend : int.MaxValue;
|
||||
int rtomin = (nodelay == 0) ? (rx_rto >> 3) : 0;
|
||||
// flush data segments
|
||||
for(int i=0;i<snd_buf.Count;i++)
|
||||
for (int i=0;i<snd_buf.Count;i++)
|
||||
{
|
||||
Segment segment=snd_buf[i];
|
||||
bool needsend = false;
|
||||
//int debug = _itimediff(cur, segment.resendts);
|
||||
if (0 == segment.xmit)
|
||||
if (segment.xmit == 0)
|
||||
{
|
||||
needsend = true;
|
||||
segment.xmit++;
|
||||
@@ -758,7 +781,7 @@ public class Kcp
|
||||
needsend = true;
|
||||
segment.xmit++;
|
||||
xmit++;
|
||||
if (0 == nodelay)
|
||||
if (nodelay == 0)
|
||||
{
|
||||
segment.rto += rx_rto;
|
||||
} else
|
||||
@@ -781,26 +804,24 @@ public class Kcp
|
||||
segment.wnd = seg.wnd;
|
||||
segment.una = rcv_nxt;
|
||||
int need = IKCP_OVERHEAD + segment.data.ReadableBytes();
|
||||
if (offset + need >= mtu)
|
||||
if (buffer.ReadableBytes() + need > mtu)
|
||||
{
|
||||
this.output.output(buffer, this, user);
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
offset = 0;
|
||||
}
|
||||
offset += segment.Encode(buffer);
|
||||
segment.Encode(buffer);
|
||||
if (segment.data.ReadableBytes() > 0)
|
||||
{
|
||||
offset += segment.data.ReadableBytes();
|
||||
buffer.WriteBytes(segment.data);
|
||||
buffer.WriteBytes(segment.data.Duplicate());
|
||||
}
|
||||
if (segment.xmit >= dead_link)
|
||||
{
|
||||
state = 0;
|
||||
state = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// flash remain segments
|
||||
if (offset > 0)
|
||||
if (buffer.ReadableBytes() > 0)
|
||||
{
|
||||
this.output.output(buffer, this, user);
|
||||
buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3);
|
||||
@@ -843,7 +864,7 @@ public class Kcp
|
||||
public void Update(long current)
|
||||
{
|
||||
this.current = (int) current;
|
||||
if (0 == updated)
|
||||
if (updated == 0)
|
||||
{
|
||||
updated = 1;
|
||||
ts_flush = this.current;
|
||||
@@ -861,7 +882,7 @@ public class Kcp
|
||||
{
|
||||
ts_flush = this.current + interval;
|
||||
}
|
||||
flush();
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,7 +900,7 @@ public class Kcp
|
||||
public int Check(long current)
|
||||
{
|
||||
int cur = (int) current;
|
||||
if (0 == updated)
|
||||
if (updated == 0)
|
||||
{
|
||||
return cur;
|
||||
}
|
||||
@@ -1039,6 +1060,26 @@ public class Kcp
|
||||
{
|
||||
return nextUpdate;
|
||||
}
|
||||
|
||||
public Object GetUser()
|
||||
{
|
||||
return user;
|
||||
}
|
||||
public bool IsStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void SetStream(bool stream)
|
||||
{
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public void SetMinRto(int min)
|
||||
{
|
||||
rx_minrto = min;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace cocosocket4unity
|
||||
{
|
||||
/// <summary>
|
||||
/// kcp客戶端程序
|
||||
/// </summary>
|
||||
public class KcpClient : KcpOnUdp
|
||||
public abstract class KcpClient : KcpOnUdp
|
||||
{
|
||||
private LinkedList<ByteBuf> sendList;
|
||||
protected volatile bool running;
|
||||
/// <summary>
|
||||
/// 初始化kcp
|
||||
@@ -19,7 +19,6 @@ namespace cocosocket4unity
|
||||
/// <param name="port">监听端口</param>
|
||||
public KcpClient(int port):base(port)
|
||||
{
|
||||
this.sendList = new LinkedList<ByteBuf>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在运行状态
|
||||
@@ -45,6 +44,14 @@ namespace cocosocket4unity
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void HandleException(Exception ex)
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
protected override void HandleTimeout()
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
/// <summary>
|
||||
/// 开启线程开始工作
|
||||
/// </summary>
|
||||
@@ -53,7 +60,7 @@ namespace cocosocket4unity
|
||||
if (!this.running)
|
||||
{
|
||||
this.running = true;
|
||||
Thread t = new Thread(new ThreadStart(run));//启动发送线程,同步发送
|
||||
Thread t = new Thread(new ThreadStart(run));//状态更新
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
}
|
||||
@@ -64,15 +71,6 @@ namespace cocosocket4unity
|
||||
{
|
||||
DateTime st = DateTime.Now;
|
||||
this.Update();
|
||||
lock (this.sendList)
|
||||
{
|
||||
while(this.sendList.Count>0)
|
||||
{
|
||||
ByteBuf bb=this.sendList.First.Value;
|
||||
sendList.RemoveFirst();
|
||||
this.kcp.Send(bb);
|
||||
}
|
||||
}
|
||||
if (this.needUpdate)
|
||||
{
|
||||
continue;
|
||||
@@ -84,68 +82,10 @@ namespace cocosocket4unity
|
||||
{
|
||||
break;
|
||||
}
|
||||
Thread.Yield();
|
||||
end = DateTime.Now;
|
||||
Thread.Sleep(0);
|
||||
end = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 处理udp的消息
|
||||
/// </summary>
|
||||
/// <param name="bb"></param>
|
||||
protected override void HandleReceive(ByteBuf bb)
|
||||
{
|
||||
string s = System.Text.Encoding.UTF8.GetString(bb.GetRaw(),0,bb.ReadableBytes());
|
||||
Console.WriteLine("收到消息: "+s);
|
||||
//this.Send(bb);//回送
|
||||
}
|
||||
/// <summary>
|
||||
/// 异常
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
protected override void HandleException(Exception ex)
|
||||
{
|
||||
Console.WriteLine("异常: " + ex);
|
||||
this.Stop();
|
||||
}
|
||||
/// <summary>
|
||||
/// 超时
|
||||
/// </summary>
|
||||
protected override void HandleTimeout()
|
||||
{
|
||||
Console.WriteLine("超时: ");
|
||||
this.Stop();
|
||||
}
|
||||
public void Send(ByteBuf content)
|
||||
{
|
||||
lock (this.sendList)
|
||||
{
|
||||
this.sendList.AddLast(content);
|
||||
this.needUpdate = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 測試
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
KcpClient client = new KcpClient(2223);
|
||||
client.NoDelay(1, 10, 2, 1);//fast
|
||||
client.WndSize(64, 64);
|
||||
client.Timeout(10*1000);
|
||||
client.Connect("10.18.121.15",2222);
|
||||
client.Start();
|
||||
Thread.Sleep(2000);
|
||||
String s = "hi,heoll world! 你好啊!!";
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
s = s + s;
|
||||
}
|
||||
ByteBuf bb = new ByteBuf(System.Text.Encoding.UTF8.GetBytes(s));
|
||||
Console.WriteLine(bb.ReadableBytes());
|
||||
client.Send(bb);
|
||||
Console.Read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace cocosocket4unity
|
||||
protected Kcp kcp;
|
||||
protected IPEndPoint serverAddr;
|
||||
protected Object LOCK = new Object();//加锁访问收到的数据
|
||||
protected LinkedList<byte[]> received;
|
||||
protected Object SEND_LOCK = new Object();//加锁访问发送列表
|
||||
protected LinkedList<ByteBuf> received;
|
||||
protected LinkedList<ByteBuf> sendList;
|
||||
protected int nodelay;
|
||||
protected int interval = Kcp.IKCP_INTERVAL;
|
||||
protected int resend;
|
||||
@@ -28,7 +30,8 @@ namespace cocosocket4unity
|
||||
{
|
||||
client = new UdpClient(port);
|
||||
kcp = new Kcp(121106, this, null);
|
||||
this.received = new LinkedList<byte[]>();
|
||||
this.received = new LinkedList<ByteBuf>();
|
||||
this.sendList = new LinkedList<ByteBuf>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 连接到地址
|
||||
@@ -69,7 +72,7 @@ namespace cocosocket4unity
|
||||
byte[] data=client.EndReceive(ar, ref this.serverAddr);
|
||||
lock(LOCK)
|
||||
{
|
||||
this.received.AddLast(data);
|
||||
this.received.AddLast(new ByteBuf(data));
|
||||
this.needUpdate = true;
|
||||
}
|
||||
client.BeginReceive(Received, ar.AsyncState);
|
||||
@@ -78,12 +81,21 @@ namespace cocosocket4unity
|
||||
this.HandleException(ex);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* update one kcp
|
||||
*
|
||||
* @param addr
|
||||
* @param kcp
|
||||
*/
|
||||
/// <summary>
|
||||
/// 发送
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
public void Send(ByteBuf content)
|
||||
{
|
||||
lock (this.SEND_LOCK)
|
||||
{
|
||||
this.sendList.AddLast(content);
|
||||
this.needUpdate = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
//input
|
||||
@@ -91,14 +103,9 @@ namespace cocosocket4unity
|
||||
{
|
||||
while (this.received.Count>0)
|
||||
{
|
||||
byte[] dp = this.received.First.Value;
|
||||
int r=kcp.Input(new ByteBuf(dp));
|
||||
ByteBuf bb = this.received.First.Value;
|
||||
kcp.Input(bb);
|
||||
this.received.RemoveFirst();
|
||||
if (r < 0)//error
|
||||
{
|
||||
this.HandleException(new Exception("kcp输入状态异常:"+r));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//receive
|
||||
@@ -112,6 +119,16 @@ namespace cocosocket4unity
|
||||
this.lastTime = DateTime.Now;
|
||||
this.HandleReceive(bb);
|
||||
}
|
||||
}
|
||||
//send
|
||||
lock (this.SEND_LOCK)
|
||||
{
|
||||
while (this.sendList.Count > 0)
|
||||
{
|
||||
ByteBuf item = this.sendList.First.Value;
|
||||
this.kcp.Send(item);
|
||||
this.sendList.RemoveFirst();
|
||||
}
|
||||
}
|
||||
//update kcp status
|
||||
int cur = (int)DateTime.Now.Ticks;
|
||||
@@ -125,7 +142,8 @@ namespace cocosocket4unity
|
||||
if (this.timeout > 0 && lastTime!=DateTime.MinValue)
|
||||
{
|
||||
double del=(DateTime.Now - this.lastTime).TotalMilliseconds;
|
||||
if (del > this.timeout) {
|
||||
if (del > this.timeout)
|
||||
{
|
||||
this.HandleTimeout();
|
||||
}
|
||||
}
|
||||
@@ -183,5 +201,20 @@ namespace cocosocket4unity
|
||||
{
|
||||
this.mtu = mtu;
|
||||
}
|
||||
public bool IsStream()
|
||||
{
|
||||
return this.kcp.IsStream();
|
||||
}
|
||||
|
||||
public void SetStream(bool stream)
|
||||
{
|
||||
this.kcp.SetStream(stream);
|
||||
}
|
||||
|
||||
public void SetMinRto(int min)
|
||||
{
|
||||
this.kcp.SetMinRto(min);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
74
cocosocket4unity/cocosocket4unity/TestKcp.cs
Normal file
74
cocosocket4unity/cocosocket4unity/TestKcp.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using LitJson;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using protocol;
|
||||
//引用的
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace cocosocket4unity
|
||||
{
|
||||
public class TestKcp : KcpClient
|
||||
{
|
||||
public TestKcp(int port): base(port)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void HandleReceive(ByteBuf bb)
|
||||
{
|
||||
string content= System.Text.Encoding.UTF8.GetString(bb.GetRaw());
|
||||
Console.WriteLine("msg:"+content);
|
||||
this.Send(bb.Copy());
|
||||
}
|
||||
/// <summary>
|
||||
/// 异常
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
protected override void HandleException(Exception ex)
|
||||
{
|
||||
base.HandleException(ex);
|
||||
}
|
||||
/// <summary>
|
||||
/// 超时
|
||||
/// </summary>
|
||||
protected override void HandleTimeout()
|
||||
{
|
||||
base.HandleTimeout();
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
KcpClient client = new TestKcp(2223);
|
||||
client.NoDelay(1, 10, 2, 1);//fast
|
||||
client.WndSize(64, 64);
|
||||
client.Timeout(10*1000);
|
||||
client.SetMtu(512);
|
||||
client.SetMinRto(10);
|
||||
client.Connect("119.29.153.92", 2222);
|
||||
//client.Connect("127.0.0.1", 2222);
|
||||
client.Start();
|
||||
Thread.Sleep(2000);
|
||||
String s = "hi,heoll world! 你好啊!!";
|
||||
//for (int i = 0; i < 2; i++)
|
||||
//{
|
||||
// s = s + s;
|
||||
//}
|
||||
ByteBuf bb = new ByteBuf(System.Text.Encoding.UTF8.GetBytes(s));
|
||||
Console.WriteLine(bb.ReadableBytes());
|
||||
client.Send(bb);
|
||||
Console.Read();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<Compile Include="ProtoAttribute.cs" />
|
||||
<Compile Include="Protocal.cs" />
|
||||
<Compile Include="LVProtocal.cs" />
|
||||
<Compile Include="TestKcp.cs" />
|
||||
<Compile Include="USocket.cs" />
|
||||
<Compile Include="SocketListner.cs" />
|
||||
<Compile Include="TestListner.cs" />
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
D:\projects\cocosocket4unity\cocosocket4unity\bin\Debug\cocosocket4unity.exe
|
||||
D:\projects\cocosocket4unity\cocosocket4unity\bin\Debug\cocosocket4unity.pdb
|
||||
D:\projects\cocosocket4unity\cocosocket4unity\obj\x86\Debug\cocosocket4unity.exe
|
||||
D:\projects\cocosocket4unity\cocosocket4unity\obj\x86\Debug\cocosocket4unity.pdb
|
||||
D:\projects\open\cocosocket\cocosocket4unity\cocosocket4unity\bin\Debug\cocosocket4unity.exe
|
||||
D:\projects\open\cocosocket\cocosocket4unity\cocosocket4unity\bin\Debug\cocosocket4unity.pdb
|
||||
D:\projects\open\cocosocket\cocosocket4unity\cocosocket4unity\bin\Debug\protobuf-net.dll
|
||||
D:\projects\open\cocosocket\cocosocket4unity\cocosocket4unity\obj\x86\Debug\cocosocket4unity.exe
|
||||
D:\projects\open\cocosocket\cocosocket4unity\cocosocket4unity\obj\x86\Debug\cocosocket4unity.pdb
|
||||
1051
unityClientSample/Assets/src/cocosocket/Kcp.cs
Normal file
1051
unityClientSample/Assets/src/cocosocket/Kcp.cs
Normal file
File diff suppressed because it is too large
Load Diff
152
unityClientSample/Assets/src/cocosocket/KcpClient.cs
Normal file
152
unityClientSample/Assets/src/cocosocket/KcpClient.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
namespace cocosocket4unity
|
||||
{
|
||||
/// <summary>
|
||||
/// kcp客戶端程序
|
||||
/// </summary>
|
||||
public abstract class KcpClient : KcpOnUdp
|
||||
{
|
||||
private LinkedList<ByteBuf> sendList;
|
||||
protected volatile bool running;
|
||||
/// <summary>
|
||||
/// 初始化kcp
|
||||
/// </summary>
|
||||
/// <param name="port">监听端口</param>
|
||||
public KcpClient(int port):base(port)
|
||||
{
|
||||
this.sendList = new LinkedList<ByteBuf>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在运行状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsRunning()
|
||||
{
|
||||
return this.running;
|
||||
}
|
||||
/// <summary>
|
||||
/// 停止udp
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if(running)
|
||||
{
|
||||
running = false;
|
||||
try
|
||||
{
|
||||
this.client.Close();
|
||||
}catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 开启线程开始工作
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (!this.running)
|
||||
{
|
||||
this.running = true;
|
||||
Thread t = new Thread(new ThreadStart(run));//启动发送线程,同步发送
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
}
|
||||
}
|
||||
private void run()
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
DateTime st = DateTime.Now;
|
||||
this.Update();
|
||||
lock (this.sendList)
|
||||
{
|
||||
while(this.sendList.Count>0)
|
||||
{
|
||||
ByteBuf bb=this.sendList.First.Value;
|
||||
sendList.RemoveFirst();
|
||||
this.kcp.Send(bb);
|
||||
}
|
||||
}
|
||||
if (this.needUpdate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
DateTime end = DateTime.Now;
|
||||
while ((end - st).TotalMilliseconds < 10)
|
||||
{
|
||||
if (this.needUpdate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Thread.Sleep(0);
|
||||
end = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 处理udp的消息
|
||||
/// </summary>
|
||||
/// <param name="bb"></param>
|
||||
// protected override void HandleReceive(ByteBuf bb)
|
||||
// {
|
||||
// short cmd = bb.ReadShort();
|
||||
// Type protocolType = MessageQueueHandler.GetProtocolType(cmd);
|
||||
// if (protocolType == null) {
|
||||
// Debug.LogWarning(cmd + " - 本地找不到该ProtocolType!");
|
||||
// return;
|
||||
// }
|
||||
// byte[] bs = bb.GetRaw();
|
||||
// MemoryStream stream = new MemoryStream(bs, bb.ReaderIndex(), bb.ReadableBytes());
|
||||
// object obj = ProtoBuf.Serializer.NonGeneric.Deserialize(protocolType, stream);
|
||||
// FieldInfo success = obj.GetType().GetField("success");
|
||||
// if (success != null) {
|
||||
// if ((bool)success.GetValue(obj) == true) {
|
||||
// MessageQueueHandler.PushQueue(cmd, obj);
|
||||
// } else {
|
||||
// FieldInfo info = obj.GetType().GetField("info");
|
||||
// if (info != null && info.GetValue(obj) != null) {
|
||||
// Debug.LogWarning("下行\t出错, cmd=" + cmd + ", type=" + MessageQueueHandler.GetProtocolType(cmd).ToString() + ", " + JsonManager.GetInstance().SerializeObjectDealVector(obj).Replace("\n", ""));
|
||||
// MessageQueueHandler.PushError(info.GetValue(obj).ToString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
/// <summary>
|
||||
/// 异常
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
// protected override void HandleException(Exception ex)
|
||||
// {
|
||||
// Debug.LogWarning("异常: " + ex);
|
||||
// this.Stop();
|
||||
// }
|
||||
/// <summary>
|
||||
/// 超时
|
||||
/// </summary>
|
||||
// protected override void HandleTimeout()
|
||||
// {
|
||||
// Debug.LogWarning("超时: ");
|
||||
// this.Stop();
|
||||
// }
|
||||
public void Send(ByteBuf content)
|
||||
{
|
||||
lock (this.sendList)
|
||||
{
|
||||
this.sendList.AddLast(content);
|
||||
this.needUpdate = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 測試
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
}
|
||||
}
|
||||
187
unityClientSample/Assets/src/cocosocket/KcpOnUdp.cs
Normal file
187
unityClientSample/Assets/src/cocosocket/KcpOnUdp.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
|
||||
namespace cocosocket4unity
|
||||
{
|
||||
public abstract class KcpOnUdp : Output
|
||||
{
|
||||
protected UdpClient client;
|
||||
protected Kcp kcp;
|
||||
protected IPEndPoint serverAddr;
|
||||
protected Object LOCK = new Object();//加锁访问收到的数据
|
||||
protected LinkedList<byte[]> received;
|
||||
protected int nodelay;
|
||||
protected int interval = Kcp.IKCP_INTERVAL;
|
||||
protected int resend;
|
||||
protected int nc;
|
||||
protected int sndwnd = Kcp.IKCP_WND_SND;
|
||||
protected int rcvwnd = Kcp.IKCP_WND_RCV;
|
||||
protected int mtu = Kcp.IKCP_MTU_DEF;
|
||||
protected volatile bool needUpdate;
|
||||
protected long timeout;//超时
|
||||
protected DateTime lastTime;//上次检测时间
|
||||
public KcpOnUdp(int port)
|
||||
{
|
||||
client = new UdpClient(port);
|
||||
kcp = new Kcp(121106, this, null);
|
||||
this.received = new LinkedList<byte[]>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 连接到地址
|
||||
/// </summary>
|
||||
public void Connect(string host,int port)
|
||||
{
|
||||
serverAddr=new IPEndPoint(IPAddress.Parse(host),port);
|
||||
//mode setting
|
||||
kcp.NoDelay(nodelay, interval, resend, nc);
|
||||
kcp.WndSize(sndwnd, rcvwnd);
|
||||
kcp.SetMtu(mtu);
|
||||
try
|
||||
{
|
||||
this.client.Connect(serverAddr);
|
||||
client.BeginReceive(Received, client);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.HandleException(ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 超时设定
|
||||
/// </summary>
|
||||
public void Timeout(long timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
public override void output(ByteBuf msg, Kcp kcp, Object user)
|
||||
{
|
||||
this.client.Send(msg.GetRaw(),msg.ReadableBytes());
|
||||
}
|
||||
private void Received(IAsyncResult ar)
|
||||
{
|
||||
UdpClient client = (UdpClient)ar.AsyncState;
|
||||
try
|
||||
{
|
||||
byte[] data=client.EndReceive(ar, ref this.serverAddr);
|
||||
lock(LOCK)
|
||||
{
|
||||
this.received.AddLast(data);
|
||||
this.needUpdate = true;
|
||||
}
|
||||
client.BeginReceive(Received, ar.AsyncState);
|
||||
}catch(Exception ex)
|
||||
{
|
||||
this.HandleException(ex);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* update one kcp
|
||||
*
|
||||
* @param addr
|
||||
* @param kcp
|
||||
*/
|
||||
public void Update()
|
||||
{
|
||||
//input
|
||||
lock (LOCK)
|
||||
{
|
||||
while (this.received.Count>0)
|
||||
{
|
||||
byte[] dp = this.received.First.Value;
|
||||
int r=kcp.Input(new ByteBuf(dp));
|
||||
this.received.RemoveFirst();
|
||||
if (r < 0)//error
|
||||
{
|
||||
this.HandleException(new Exception("kcp输入状态异常:"+r));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//receive
|
||||
int len;
|
||||
while ((len = kcp.PeekSize()) > 0)
|
||||
{
|
||||
ByteBuf bb = new ByteBuf(len);
|
||||
int n = kcp.Receive(bb);
|
||||
if (n > 0)
|
||||
{
|
||||
this.lastTime = DateTime.Now;
|
||||
this.HandleReceive(bb);
|
||||
}
|
||||
}
|
||||
//update kcp status
|
||||
int cur = (int)DateTime.Now.Ticks;
|
||||
if (this.needUpdate|| cur >= kcp.GetNextUpdate())
|
||||
{
|
||||
kcp.Update(cur);
|
||||
kcp.SetNextUpdate(kcp.Check(cur));
|
||||
this.needUpdate = false;
|
||||
}
|
||||
//check timeout
|
||||
if (this.timeout > 0 && lastTime!=DateTime.MinValue)
|
||||
{
|
||||
double del=(DateTime.Now - this.lastTime).TotalMilliseconds;
|
||||
if (del > this.timeout) {
|
||||
this.HandleTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 处理收到的消息
|
||||
*/
|
||||
protected abstract void HandleReceive(ByteBuf bb);
|
||||
/// <summary>
|
||||
/// 处理异常
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
protected abstract void HandleException(Exception ex);
|
||||
/// <summary>
|
||||
/// 超时处理
|
||||
/// </summary>
|
||||
protected abstract void HandleTimeout();
|
||||
/**
|
||||
* fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) nodelay: 0:disable(default),
|
||||
* 1:enable interval: internal update timer interval in millisec, default is
|
||||
* 100ms resend: 0:disable fast resend(default), 1:enable fast resend nc:
|
||||
* 0:normal congestion control(default), 1:disable congestion control
|
||||
*
|
||||
* @param nodelay
|
||||
* @param interval
|
||||
* @param resend
|
||||
* @param nc
|
||||
*/
|
||||
public void NoDelay(int nodelay, int interval, int resend, int nc)
|
||||
{
|
||||
this.nodelay = nodelay;
|
||||
this.interval = interval;
|
||||
this.resend = resend;
|
||||
this.nc = nc;
|
||||
}
|
||||
|
||||
/**
|
||||
* set maximum window size: sndwnd=32, rcvwnd=32 by default
|
||||
*
|
||||
* @param sndwnd
|
||||
* @param rcvwnd
|
||||
*/
|
||||
public void WndSize(int sndwnd, int rcvwnd)
|
||||
{
|
||||
this.sndwnd = sndwnd;
|
||||
this.rcvwnd = rcvwnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* change MTU size, default is 1400
|
||||
*
|
||||
* @param mtu
|
||||
*/
|
||||
public void SetMtu(int mtu)
|
||||
{
|
||||
this.mtu = mtu;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
unityClientSample/Assets/src/cocosocket/TestKcp.cs
Normal file
71
unityClientSample/Assets/src/cocosocket/TestKcp.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using LitJson;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using protocol;
|
||||
//引用的
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace cocosocket4unity
|
||||
{
|
||||
public class TestKcp : KcpClient
|
||||
{
|
||||
public TestKcp(int port): base(port)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void HandleReceive(ByteBuf bb)
|
||||
{
|
||||
string content= System.Text.Encoding.UTF8.GetString(bb.GetRaw());
|
||||
Console.WriteLine("msg:"+content);
|
||||
}
|
||||
/// <summary>
|
||||
/// 异常
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
protected override void HandleException(Exception ex)
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
/// <summary>
|
||||
/// 超时
|
||||
/// </summary>
|
||||
protected override void HandleTimeout()
|
||||
{
|
||||
this.Stop();
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
KcpClient client = new TestKcp(2223);
|
||||
client.NoDelay(1, 10, 2, 1);//fast
|
||||
client.WndSize(64, 64);
|
||||
client.Timeout(10*1000);
|
||||
client.SetMtu(1000);
|
||||
client.Connect("119.29.153.92", 2222);
|
||||
client.Start();
|
||||
Thread.Sleep(2000);
|
||||
String s = "hi,heoll world! 你好啊!!";
|
||||
//for (int i = 0; i < 2; i++)
|
||||
//{
|
||||
// s = s + s;
|
||||
//}
|
||||
ByteBuf bb = new ByteBuf(System.Text.Encoding.UTF8.GetBytes(s));
|
||||
Console.WriteLine(bb.ReadableBytes());
|
||||
client.Send(bb);
|
||||
Console.Read();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user