313 lines
8.2 KiB
C#
313 lines
8.2 KiB
C#
/********************************************************************************
|
||
* 文件名:SocketOutputStream.cs
|
||
* 全路径: \NetWork\SocketAPI\SocketOutputStream.cs
|
||
* 创建人: 王华
|
||
* 创建时间:2013-11-29
|
||
*
|
||
* 功能说明: Socket的应用层输出缓冲区
|
||
*
|
||
* 修改记录:
|
||
*********************************************************************************/
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Net;
|
||
#if UNITY_WP8
|
||
using UnityPortSocket;
|
||
#else
|
||
using System.Net.Sockets;
|
||
#endif
|
||
using System.Text;
|
||
|
||
#pragma warning disable
|
||
|
||
namespace SPacket.SocketInstance
|
||
{
|
||
public class SocketOutputStream
|
||
{
|
||
public const bool FALSE = false;
|
||
public const bool TRUE = true;
|
||
public const uint SOCKET_ERROR = 0xFFFFFFFF;
|
||
public const uint DEFAULT_SOCKET_OUTPUT_BUFFER_SIZE = 1024 * 8;
|
||
public const uint DISCONNECT_SOCKET_OUTPUT_BUFFER_SIZE = 1024 * 20;
|
||
|
||
public SocketOutputStream( SocketInstance sock,
|
||
uint BufferLen = DEFAULT_SOCKET_OUTPUT_BUFFER_SIZE,
|
||
uint MaxBufferLen = DISCONNECT_SOCKET_OUTPUT_BUFFER_SIZE)
|
||
{
|
||
m_pSocket = sock;
|
||
m_BufferLen = BufferLen;
|
||
m_MaxBufferLen = MaxBufferLen;
|
||
m_Head = 0;
|
||
m_Tail = 0;
|
||
m_Buffer = new Byte[m_BufferLen];
|
||
m_BufferTemp = new Byte[m_BufferLen];
|
||
}
|
||
|
||
void ClearBufferTemp()
|
||
{
|
||
if (m_BufferTemp != null)
|
||
{
|
||
int nCount = m_BufferTemp.Length;
|
||
Array.Clear(m_BufferTemp, 0, nCount);
|
||
}
|
||
}
|
||
|
||
public uint Write (Byte[] buf, uint len)
|
||
{
|
||
uint nFree = ((m_Head <= m_Tail) ? (m_BufferLen - m_Tail + m_Head - 1) : (m_Head - m_Tail - 1));
|
||
|
||
if (len >= nFree)
|
||
{
|
||
if (!Resize(len - nFree + 1))
|
||
return 0;
|
||
}
|
||
|
||
if (m_Head <= m_Tail)
|
||
{
|
||
if (m_Head == 0)
|
||
{
|
||
nFree = m_BufferLen - m_Tail - 1;
|
||
// memcpy(&m_Buffer[m_Tail], buf, len);
|
||
for (int i = 0; i < len;++i )
|
||
{
|
||
m_Buffer[m_Tail + i] = buf[i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
nFree = m_BufferLen - m_Tail;
|
||
if (len <= nFree)
|
||
{
|
||
//memcpy(&m_Buffer[m_Tail], buf, len);
|
||
for (int i = 0; i < len; ++i)
|
||
{
|
||
m_Buffer[m_Tail + i] = buf[i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//memcpy(&m_Buffer[m_Tail], buf, nFree);
|
||
for (int i = 0; i < nFree; ++i)
|
||
{
|
||
m_Buffer[m_Tail + i] = buf[i];
|
||
}
|
||
for (int i = 0; i < len - nFree; ++i)
|
||
{
|
||
m_Buffer[i] = buf[nFree+i];
|
||
}
|
||
// memcpy(m_Buffer, &buf[nFree], len - nFree);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// memcpy(&m_Buffer[m_Tail], buf, len);
|
||
for (int i = 0; i < len; ++i)
|
||
{
|
||
m_Buffer[m_Tail + i] = buf[i];
|
||
}
|
||
}
|
||
|
||
m_Tail = (m_Tail + len) % m_BufferLen;
|
||
|
||
return len;
|
||
}
|
||
|
||
public uint Flush ()
|
||
{
|
||
|
||
if (m_pSocket == null) return 0;
|
||
|
||
uint nFlushed = 0;
|
||
uint nSent = 0;
|
||
uint nLeft;
|
||
SocketFlags flag = SocketFlags.None;
|
||
|
||
if (m_BufferLen > m_MaxBufferLen)
|
||
{
|
||
Initsize();
|
||
return SOCKET_ERROR;
|
||
}
|
||
try
|
||
{
|
||
if ( m_Head < m_Tail )
|
||
{
|
||
nLeft = m_Tail - m_Head;
|
||
|
||
while ( nLeft > 0 )
|
||
{
|
||
ClearBufferTemp();
|
||
for (int i=0;i<nLeft;++i)
|
||
{
|
||
m_BufferTemp[i] = m_Buffer[m_Head+i];
|
||
}
|
||
nSent = m_pSocket.Send(m_BufferTemp, (int)nLeft, flag);
|
||
//LogModule.DebugLog(nSent.ToString());
|
||
//if (nSent==SOCKET_ERROR_WOULDBLOCK) return 0 ;
|
||
if (nSent==SOCKET_ERROR) return SOCKET_ERROR ;
|
||
if (nSent==0) return 0;
|
||
|
||
nFlushed += nSent;
|
||
nLeft -= nSent;
|
||
m_Head += nSent;
|
||
}
|
||
|
||
|
||
|
||
}
|
||
else if( m_Head > m_Tail )
|
||
{
|
||
nLeft = m_BufferLen - m_Head;
|
||
|
||
while ( nLeft > 0 )
|
||
{
|
||
ClearBufferTemp();
|
||
for (int i=0;i<nLeft;++i)
|
||
{
|
||
m_BufferTemp[i] = m_Buffer[m_Head+i];
|
||
}
|
||
|
||
nSent = m_pSocket.Send(m_BufferTemp , (int)nLeft , flag );
|
||
//if (nSent==SOCKET_ERROR_WOULDBLOCK) return 0 ;
|
||
if (nSent==SOCKET_ERROR) return SOCKET_ERROR-3 ;
|
||
if (nSent==0) return 0;
|
||
|
||
nFlushed += nSent;
|
||
nLeft -= nSent;
|
||
m_Head += nSent;
|
||
}
|
||
|
||
// Assert( m_Head == m_BufferLen );
|
||
|
||
m_Head = 0;
|
||
|
||
nLeft = m_Tail;
|
||
|
||
while ( nLeft > 0 )
|
||
{
|
||
ClearBufferTemp();
|
||
for (int i=0;i<nLeft;++i)
|
||
{
|
||
m_BufferTemp[i] = m_Buffer[m_Head + i];
|
||
}
|
||
|
||
nSent = m_pSocket.Send(m_BufferTemp, (int)nLeft, flag);
|
||
//if (nSent==SOCKET_ERROR_WOULDBLOCK) return 0 ;
|
||
if (nSent==SOCKET_ERROR) return SOCKET_ERROR ;
|
||
if (nSent==0) return 0;
|
||
|
||
nFlushed += nSent;
|
||
nLeft -= nSent;
|
||
m_Head += nSent;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
}
|
||
catch
|
||
{
|
||
if( nSent>0 )
|
||
{
|
||
m_Head += nSent;
|
||
}
|
||
}
|
||
|
||
m_Head = m_Tail = 0 ;
|
||
|
||
return nFlushed;
|
||
|
||
}
|
||
public void Initsize (uint BufferLen = DEFAULT_SOCKET_OUTPUT_BUFFER_SIZE)
|
||
{
|
||
m_Head = 0;
|
||
m_Tail = 0;
|
||
if (BufferLen > m_MaxBufferLen)
|
||
{
|
||
BufferLen = m_MaxBufferLen;
|
||
}
|
||
|
||
m_Buffer = new Byte[BufferLen];
|
||
m_BufferLen = BufferLen;
|
||
}
|
||
public bool Resize( uint size )
|
||
{
|
||
|
||
uint orgSize = size;
|
||
|
||
size = Math.Max(size, (uint)(m_BufferLen >> 1));
|
||
uint newBufferLen = m_BufferLen + size;
|
||
uint len = Length();
|
||
|
||
if (size < 0)
|
||
{
|
||
if (newBufferLen < 0 || newBufferLen < len)
|
||
return false;
|
||
}
|
||
|
||
Byte[] newBuffer = new Byte[newBufferLen];
|
||
if (newBuffer == null)
|
||
return false;
|
||
|
||
if (m_Head < m_Tail)
|
||
{
|
||
// memcpy(newBuffer, &m_Buffer[m_Head], m_Tail - m_Head);
|
||
for (int i = 0; i < m_Tail - m_Head;++i )
|
||
{
|
||
newBuffer[i] = m_Buffer[m_Head + i];
|
||
}
|
||
}
|
||
else if (m_Head > m_Tail)
|
||
{
|
||
//memcpy(newBuffer, &m_Buffer[m_Head], m_BufferLen - m_Head);
|
||
for (int i = 0; i < m_BufferLen - m_Head; ++i)
|
||
{
|
||
newBuffer[i] = m_Buffer[m_Head + i];
|
||
}
|
||
|
||
//memcpy(&newBuffer[m_BufferLen - m_Head], m_Buffer, m_Tail);
|
||
for (int i = 0; i < m_Tail; ++i)
|
||
{
|
||
newBuffer[m_BufferLen - m_Head + i] = m_Buffer[i];
|
||
}
|
||
}
|
||
m_Buffer = newBuffer;
|
||
m_BufferLen = newBufferLen;
|
||
m_Head = 0;
|
||
m_Tail = len;
|
||
|
||
return true;
|
||
}
|
||
|
||
public uint Length ()
|
||
{
|
||
if (m_Head < m_Tail)
|
||
return m_Tail - m_Head;
|
||
|
||
else if (m_Head > m_Tail)
|
||
return m_BufferLen - m_Head + m_Tail;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
public void CleanUp ()
|
||
{
|
||
m_Head = 0;
|
||
m_Tail = 0;
|
||
}
|
||
|
||
SocketInstance m_pSocket;
|
||
Byte[] m_Buffer = null;
|
||
Byte[] m_BufferTemp = null; //临时缓存,解决new的GC问题
|
||
|
||
uint m_BufferLen;
|
||
uint m_MaxBufferLen;
|
||
uint m_Head;
|
||
uint m_Tail;
|
||
}
|
||
}
|