public partial class Form1 : Form
{
//声明Tcp客户端
private TcpClient tc; //声明网络流
private static NetworkStream ns;
public Form1()
{
CheckForIllegalCrossThreadCalls = false; InitializeComponent(); tc = new TcpClient("localhost", 8888);
} private void button1_Click(object sender, EventArgs e)
{
//注册本机8888端口
//tc = new TcpClient("localhost", 8888); //实例化网络流对象
ns = tc.GetStream(); // 第二次运行时报错:不允许对非连接的套接字执行此操作
string temp = this.textBox1.Text; StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns); //将TextBox1的值传给服务器端
sw.WriteLine(temp);
sw.Flush(); //接收服务器端回传的字符串
string str = sr.ReadLine();
this.textBox2.Text = str;
sr.Close();
sw.Close();
}
不允许对非连接的套接字执行此操作,估计是连接失效,怎样才能建立一个静态链接呢?
参考这里:http://hi.baidu.com/dongdongjiao/blog/item/2c81092230d4d1a74723e85e.html
非也,错误原因是你的
StreamReader sr = new StreamReader(ns);虽然那个ns可以作为一般的流传递,但是你这样是错误的。网络流如果这样传递了,意味着必须要关闭ns后,才能读取它,ns流自动关闭了,你当然无法再次使用了,除非创建新的TcpClient,并获取新的网络流对象
感觉是这么一回事。 如果我不希望用NetworkStream ,就希望发送byte,应该修改呢?
不用监听的,首先这是客户端,不是服务端代码。其次TcpClient.GetStream()返回的流对象是可以直接读写的,简化了操作,不过功能上还是有一些弊端的,就好像这段代码里,如果整个对象传递给另一个流使用时,就会发生自动关闭网络流连接的情况。
请问怎样把现在的程序改用Socket呢?能给段代码吗?
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;namespace FBug.Framework.Communication
{
/// <summary>
/// 通讯器
/// </summary>
public class Communicator : IDisposable
{
#region Properties
/// <summary>
/// 默认的通讯超时时间
/// </summary>
private const int c_Timeout = -1;
/// <summary>
/// 最后接收的命令
/// </summary>
private List<CommandBase> m_LastSynReceivedCommands;
/// <summary>
/// 数据交互流
/// </summary>
private NetworkStream m_NetworkStream;
/// <summary>
/// 处理接收的线程(后台)
/// </summary>
private BackgroundWorker m_Receiver;
/// <summary>
/// 监听的套接字
/// </summary>
private Socket m_Socket;
/// <summary>
/// 连线时钟
/// </summary>
private Timer m_Timer;
/// <summary>
/// 所有者
/// </summary>
private object m_Owner;
/// <summary>
/// 远程主机
/// </summary>
private IPEndPoint m_RemoteEndpoint;
/// <summary>
/// 连接超时时间
/// </summary>
private int m_Timeout = c_Timeout;
/// <summary>
/// 关闭前的数据发送延时(Default: 5s)
/// </summary>
private int m_LingerSecond = 5;
/// <summary>
/// 每次接收数据默认长度
/// </summary>
private int m_BufSize = 4; /// <summary>
/// 同步发送锁
/// </summary>
private static readonly object s_SynSendLock = new object();
/// <summary>
/// 发送数据锁
/// </summary>
private static readonly object s_SendLock = new object(); /// <summary>
/// 通讯器的所有者
/// </summary>
public object Owner
{
get { return m_Owner; }
}
/// <summary>
/// 最后接收到得指令
/// </summary>
public List<CommandBase> LastSynReceivedCommands
{
get { return m_LastSynReceivedCommands; }
}
/// <summary>
/// 获取远程主机Ip地址。
/// </summary>
public IPAddress IpAddress
{
get
{
if (m_RemoteEndpoint == null)
{
return IPAddress.None;
} return m_RemoteEndpoint.Address;
}
}
/// <summary>
/// 获取远程主机端口号(-1为无效)。
/// </summary>
public int Port
{
get
{
if (m_RemoteEndpoint == null)
{
return -1;
} return m_RemoteEndpoint.Port;
}
}
/// <summary>
/// 是否已连接。
/// </summary>
public bool Connected
{
get
{
if (m_Socket == null)
{
return false;
} return m_Socket.Connected;
}
}
/// <summary>
/// 连接超时时间(Default: -1s)
/// </summary>
public int CommunicationTimeout
{
get { return m_Timeout; }
set
{
if (m_Timeout == value)
{
return;
} // 停止时钟
if (value <= 0)
{
this.TryStopTimer(); m_Timeout = c_Timeout;
return;
} // 重启时钟
if (m_Timer != null)
{
this.ReWaitingTimer();
return;
} m_Timeout = value; // 启动时钟
this.StartTimer();
}
}
/// <summary>
/// 关闭前的数据发送延时(Default: 5s)
/// </summary>
public int LingerSecond
{
get { return m_LingerSecond; }
set { m_LingerSecond = value; }
}
/// <summary>
/// 每次接收数据默认长度(Default: 4b)
/// </summary>
public int BufferSize
{
get { return m_BufSize; }
set { m_BufSize = value; }
}
#endregion #region delegates Events
/// <summary>
/// 接收到Command后的处理。
/// </summary>
public event CommandReceivedEventHandler CommandReceived; /// <summary>
/// 接收到数据后处理,分析并创建消息。
/// 如果重写OnNetworkStreamReceiving,将需要主动引发该事件。
/// </summary>
public event BufferReceivedEventHandler BufferReceived; /// <summary>
/// 命名已发送后的处理
/// </summary>
public event CommandSentEventHandler CommandSent; /// <summary>
/// 连接断开后的处理
/// </summary>
public event EventHandler Disconnected;
#endregion #region constractor
#region CommunicationFactory
/// <summary>
/// 创建客户端的Communicator连接
/// </summary>
/// <param name="ip"></param>
/// <param name="serverPort"></param>
/// <returns></returns>
public static Communicator CreateClientCommunication(string remoteIp, int remotePort)
{
return Communicator.CreateClientCommunication(IPAddress.Parse(remoteIp), remotePort);
}
/// <summary>
/// 创建客户端的Communicator并连接
/// </summary>
/// <param name="ip"></param>
/// <param name="serverPort"></param>
/// <returns></returns>
public static Communicator CreateClientCommunication(IPAddress remoteIp, int remotePort)
{
return InitializeComponent(new Communicator(), remoteIp, remotePort);
}
/// <summary>
/// 创建客户端的Communicator并连接
/// </summary>
/// <param name="onwer"></param>
/// <param name="remoteIp"></param>
/// <param name="remotePort"></param>
/// <returns></returns>
public static Communicator CreateClientCommunication(object onwer, IPAddress remoteIp, int remotePort)
{
return InitializeComponent(new Communicator(onwer), remoteIp, remotePort);
}
/// <summary>
/// 创建客户端的Communicator并连接
/// </summary>
/// <param name="remoteIp"></param>
/// <param name="remotePort"></param>
/// <returns></returns>
public static Communicator CreateClientCommunication<T>(IPAddress remoteIp, int remotePort) where T : Communicator
{
return InitializeComponent(Activator.CreateInstance(typeof(T), true) as Communicator, remoteIp, remotePort);
}
/// <summary>
/// 创建客户端的Communicator并连接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="onwer"></param>
/// <param name="remoteIp"></param>
/// <param name="remotePort"></param>
/// <returns></returns>
public static Communicator CreateClientCommunication<T>(object onwer, IPAddress remoteIp, int remotePort) where T : Communicator
{
return InitializeComponent(Activator.CreateInstance(typeof(T), onwer) as Communicator, remoteIp, remotePort);
}
/// <summary>
///
/// </summary>
/// <param name="communicator"></param>
private static Communicator InitializeComponent(Communicator communicator, IPAddress remoteIp, int remotePort)
{
communicator.m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
communicator.m_Socket.ExclusiveAddressUse = true;
communicator.m_Socket.NoDelay = true;
communicator.m_Socket.LingerState = new LingerOption(true, communicator.LingerSecond); communicator.m_RemoteEndpoint = new IPEndPoint(remoteIp, remotePort);
communicator.Connect(); communicator.InitializeComponent();
return communicator;
}
#endregion
#region Communicator
/// <summary>
/// m_Socket创建好后执行。
/// </summary>
private void InitializeComponent()
{
m_NetworkStream = new NetworkStream(m_Socket, true); m_Receiver = new BackgroundWorker();
m_Receiver.WorkerSupportsCancellation = true;
m_Receiver.DoWork += new DoWorkEventHandler(m_Receiver_StartReceiving);
m_Receiver.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_Receiver_CompletedReceive);
}
/// <summary>
/// Communicator
/// </summary>
private Communicator() { }
/// <summary>
/// Communicator
/// </summary>
protected Communicator(object onwer) : this() { m_Owner = onwer; }
/// <summary>
/// 监听服务创建客户端管理的Communicator并连接
/// </summary>
/// <param name="socket"></param>
public Communicator(Socket socket, object onwer) : this(onwer)
{
m_Socket = socket;
m_RemoteEndpoint = socket.RemoteEndPoint as IPEndPoint; this.InitializeComponent();
}
#endregion
/// <summary>
/// Communicator
/// </summary>
~Communicator()
{
this.Dispose(false);
}
#endregion
/// <summary>
/// 连接远程主机
/// </summary>
/// <returns></returns>
public void Connect()
{
m_Socket.Connect(m_RemoteEndpoint);
}
/// <summary>
/// 开始作业,等待接收。
/// </summary>
public void StartReceiving()
{
m_Receiver.RunWorkerAsync();
} /// <summary>
/// 停止作业,停止接收。
/// </summary>
public void StopReceiving()
{
m_Receiver.CancelAsync();
}
#region public int SendCommand(CommandBase command)
#region Async Send
/// <summary>
/// 异步发送命令
/// </summary>
/// <param name="command"></param>
public void SendAsync(CommandBase command)
{
this.SendAsync(command.ToByties());
}
/// <summary>
/// 异步发送指令
/// </summary>
/// <param name="buffer"></param>
public void SendAsync(byte[] buffer)
{
this.SendAsync(buffer, 0, buffer.Length);
}
/// <summary>
/// 异步发送指令
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <returns></returns>
public void SendAsync(byte[] buffer, int offset, int size)
{
//SocketError error;
//int num = m_Socket.Send(buffer, offset, size, SocketFlags.None, out error);
//if (error != SocketError.Success)
//{
// throw new SocketException((int)error);
//} BackgroundWorker bwSendAsync = new BackgroundWorker();
bwSendAsync.WorkerSupportsCancellation = false;
bwSendAsync.DoWork += new DoWorkEventHandler(bwSendAsync_DoWork);
bwSendAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwSendAsync_RunWorkerCompleted); bwSendAsync.RunWorkerAsync(new object[] { buffer, offset, size });
}
#endregion
/// <summary>
/// 同步发送命令
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public List<CommandBase> SendCommand(CommandBase command)
{
return this.SendCommand(command.ToByties());
}
/// <summary>
/// 同步发送指令
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public List<CommandBase> SendCommand(byte[] buffer)
{
return this.SendCommand(buffer, 0, buffer.Length);
}
/// <summary>
/// 同步发送指令
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <returns></returns>
public List<CommandBase> SendCommand(byte[] buffer, int offset, int size)
{
lock (s_SynSendLock)
{
m_LastSynReceivedCommands = null; this.DoSend(buffer, offset, size);
int iMaxTimeout = m_LingerSecond * 200;
int i = 0;
while (m_LastSynReceivedCommands == null && i++ < iMaxTimeout)
{
Thread.Sleep(5);
}
if (m_LastSynReceivedCommands == null)
{
m_LastSynReceivedCommands = new List<CommandBase>();
} return m_LastSynReceivedCommands;
}
}
/// <summary>
/// 忽略同步锁的条件下发送指令
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <returns></returns>
public void Send(byte[] buffer, int offset, int size)
{
this.DoSend(buffer, offset, size);
}
#endregion
#endregion #region StartingReceive, ReceiveCompleted
/// <summary>
/// 开始接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_Receiver_StartReceiving(object sender, DoWorkEventArgs e)
{
byte[] buf = new byte[m_BufSize]; while (m_Socket.Connected)
{
if (m_Receiver.CancellationPending)
{
e.Cancel = true;
break;
} List<CommandBase> cmds;
if (this.OnNetworkStreamReceiving(m_NetworkStream, out cmds))
{
m_LastSynReceivedCommands = cmds;
} Thread.Sleep(10);
}
} /// <summary>
/// 接收结束
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_Receiver_CompletedReceive(object sender, RunWorkerCompletedEventArgs e)
{
this.Completed();
} /// <summary>
/// 接收处理
/// 引发:BufferReceived事件
/// </summary>
/// <param name="stream"></param>
/// <param name="cmds"></param>
/// <returns></returns>
protected virtual bool OnNetworkStreamReceiving(NetworkStream stream, out List<CommandBase> cmds)
{
cmds = null; byte[] buf = new byte[m_BufSize];
byte[] buffer; if (this.Received(ref buf, out buffer))
{
BufferEventArgs be = new BufferEventArgs(buffer);
this.OnBufferReceived(be); cmds = be.Commands;
return true;
} return false;
} /// <summary>
/// 接收数据
/// </summary>
/// <param name="origBuf">存储最后一次取到的数据</param>
/// <param name="outBuf">总数据</param>
/// <returns></returns>
private bool Received(ref byte[] origBuf, out byte[] outBuf)
{
// lockd at here, if needs
return this.ReceiveStream(m_NetworkStream, ref origBuf, out outBuf);
} /// <summary>
/// 接收数据
/// </summary>
/// <param name="stream"></param>
/// <param name="origBuf">存储最后一次取到的数据</param>
/// <param name="outBuf">总数据</param>
/// <returns></returns>
private bool ReceiveStream(NetworkStream stream, ref byte[] origBuf, out byte[] outBuf)
{
outBuf = null; if (!stream.DataAvailable)
{
return false;
} List<Byte> bufList = new List<byte>();
int total = 0;
while (stream.DataAvailable)
{
int len = this.TryReceive(stream, origBuf, 0, m_BufSize);
if (len <= 0)
{
break;
} bufList.AddRange(origBuf);
total += len;
if (len < m_BufSize)
{
bufList.RemoveRange(total, m_BufSize - len);
break;
}
} if (total == 0)
{
return false;
} this.ReWaitingTimer(); outBuf = bufList.ToArray();
return true;
}
/// <summary>
/// TryReceive
/// </summary>
/// <param name="stream"></param>
/// <param name="origBuf"></param>
/// <param name="outBuf"></param>
/// <returns></returns>
private int TryReceive(NetworkStream stream, byte[] buffer, int offset, int size)
{
//try
//{
//}
//catch (IOException)
//{
//} //Array.Clear(buffer, offset, size);
return stream.Read(buffer, offset, size);
} /// <summary>
/// 接收结束
/// </summary>
private void Completed()
{
if (!m_Socket.Connected)
{
return;
} this.OnCompleted();
}
#endregion
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bwSendAsync_DoWork(object sender, DoWorkEventArgs e)
{
if (!this.Connected)
{
e.Cancel = true;
return;
} object[] oList = e.Argument as object[];
if (oList == null || oList.Length != 3)
{
e.Cancel = true;
return;
} byte[] buffer = oList[0] as byte[];
int offset = (int)oList[1];
int size = (int)oList[2]; this.DoSend(buffer, offset, size);
}
/// <summary>
/// 发送结束
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void bwSendAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
using (sender as IDisposable)
{
if (e.Cancelled || e.Error != null)
{
return;
} // byte[] result = e.Result as byte[];
}
}
/// <summary>
/// 后台发送
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
private void DoSend(byte[] buffer, int offset, int size)
{
if (!m_Socket.Connected)
{
throw new SocketException((int)SocketError.Shutdown);
} lock (s_SendLock)
{
this.ReWaitingTimer(); if (!m_Socket.Connected)
{
throw new SocketException((int)SocketError.Shutdown);
} m_NetworkStream.Write(buffer, offset, size);
m_NetworkStream.Flush();
}
}
#endregion #region OnEventInvoek
/// <summary>
/// 引发命名已接收事件
/// </summary>
/// <param name="e"></param>
protected virtual void OnCommandReceived(CommandEventArgs e)
{
if (CommandReceived != null)
{
CommandReceived(this, e);
}
} /// <summary>
/// 引发数据已接收事件。
/// </summary>
/// <param name="e"></param>
protected virtual void OnBufferReceived(BufferEventArgs e)
{
if (BufferReceived != null)
{
BufferReceived(this, e);
} foreach (CommandBase cb in e.Commands)
{
this.OnCommandReceived(new CommandEventArgs(cb));
}
} /// <summary>
/// 引发 命令已发送事件。
/// </summary>
/// <param name="e"></param>
protected virtual void OnCommandSent(EventArgs e)
{
if (CommandSent != null)
{
CommandSent(this, e);
}
} /// <summary>
/// 引发连接断开事件。
/// </summary>
/// <param name="e"></param>
protected virtual void OnDisconnected(EventArgs e)
{
if (Disconnected != null)
{
Disconnected(this, e);
}
} /// <summary>
/// 引发通讯完成事件。
/// </summary>
protected virtual void OnCompleted()
{
this.TryStopTimer(); CommunicationHelper.CloseSocket(m_Socket);
m_NetworkStream.Close(); this.OnDisconnected(EventArgs.Empty);
}
#endregion #region Timer
/// <summary>
/// 以流逝时间
/// </summary>
private int m_TimerIncrease;
/// <summary>
/// 启动时钟检测超时
/// </summary>
private void StartTimer()
{
m_Timer = new Timer(new TimerCallback(TimerCallBack));
m_Timer.Change(0, 1000);
}
/// <summary>
/// 停止时钟检测超时
/// </summary>
private void TryStopTimer()
{
if (m_Timer != null)
{
m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
m_Timer.Dispose();
m_Timer = null;
}
}
/// <summary>
/// 重新计时
/// </summary>
private void ReWaitingTimer()
{
Interlocked.Exchange(ref m_TimerIncrease, 0);
}
/// <summary>
///
/// </summary>
/// <param name="args"></param>
private void TimerCallBack(object args)
{
if (m_Timeout == c_Timeout)
{
return;
} Interlocked.Increment(ref m_TimerIncrease);
if (m_Timeout == Interlocked.CompareExchange(ref m_TimerIncrease, m_Timeout, 0))
{
this.Completed();
}
}
#endregion #region private method
#endregion
#region IDisposable Members
/// <summary>
///
/// </summary>
private bool m_Disposed = false;
/// <summary>
/// Dispose
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (m_Disposed)
{
return;
} this.Completed(); if (disposing)
{
m_NetworkStream.Dispose();
m_Receiver.Dispose();
} m_Disposed = true;
}
/// <summary>
///
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
很臭很长。
CommandBase.csusing System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;namespace FBug.Framework.Communication
{
/// <summary>
/// CommandBase
/// 基础通讯包结构定义
/// </summary>
public abstract class CommandBase
{
#region member
/// <summary>
/// 空数据
/// </summary>
protected static readonly byte[] EmptyByties = { }; /// <summary>
/// 内容
/// </summary>
private byte[] m_Content = CommandBase.EmptyByties;
/// <summary>
/// 参数
/// </summary>
private List<string> m_Args;
#endregion #region Property
/// <summary>
/// 指令附加的数据内容
/// </summary>
protected byte[] Content { get { return m_Content; } } /// <summary>
/// 2字节内容
/// </summary>
public abstract string CommandType { get; } /// <summary>
/// 指令参数列表
/// </summary>
public List<string> CommandArgs
{
get
{
if (m_Args == null)
{
m_Args = new List<string>();
} return m_Args;
}
}
#endregion #region constractor
/// <summary>
/// CommandBase
/// </summary>
public CommandBase() { }
/// <summary>
/// CommandBase
/// </summary>
/// <param name="content"></param>
public CommandBase(byte[] content) : this() { m_Content = content; }
#endregion #region abstract method : Fill, ToByties
/// <summary>
/// 使用指定的数据填充本实例
/// </summary>
/// <param name="byties"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <returns></returns>
protected abstract bool Fill(byte[] byties, int offset, int size); /// <summary>
/// 使用指定的数据填充本实例
/// </summary>
/// <param name="currentSplit"></param>
/// <param name="stream"></param>
/// <returns></returns>
protected abstract bool Fill(byte currentSplit, NetworkStream stream); /// <summary>
/// 转换为流内容。
/// </summary>
/// <returns></returns>
public abstract byte[] ToByties();
#endregion
}
}
CommandEventArgs.csusing System;
using System.Collections.Generic;namespace FBug.Framework.Communication
{
/// <summary>
/// Occurs when some data received from remote.
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">The received byte[] buffer</param>
public delegate void BufferReceivedEventHandler(object sender, BufferEventArgs e); /// <summary>
/// Occurs when a command received from a client.
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">The received command object.</param>
public delegate void CommandReceivedEventHandler(object sender, CommandEventArgs e); /// <summary>
/// Occurs when a command had been sent to the remote client successfully.
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">EventArgs.</param>
public delegate void CommandSentEventHandler(object sender, EventArgs e); /// <summary>
/// Occurs when a command sending action had been failed.This is because disconnection or sending exception.
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">EventArgs.</param>
public delegate void CommandSendingFailedEventHandler(object sender, EventArgs e);
/// <summary>
/// The class that contains list about received data
/// you need invoke some CommandReceived event
/// </summary>
public class BufferEventArgs : EventArgs
{
/// <summary>
/// The received data
/// </summary>
private byte[] m_Byties; /// <summary>
/// invoking commands
/// </summary>
private List<CommandBase> m_Commands; /// <summary>
/// The received data
/// </summary>
public byte[] Byties
{
get { return m_Byties; }
} /// <summary>
/// invoking commands
/// </summary>
public List<CommandBase> Commands
{
get { return m_Commands; }
} /// <summary>
/// Creates an instance of BufferEventArgs class.
/// </summary>
/// <param name="byties"></param>
public BufferEventArgs(byte[] byties)
{
m_Byties = byties;
m_Commands = new List<CommandBase>();
} /// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return base.ToString();
}
} /// <summary>
/// The class that contains information about received command.
/// </summary>
public class CommandEventArgs : EventArgs
{
private CommandBase m_Command;
/// <summary>
/// The received command.
/// </summary>
public CommandBase Command
{
get { return m_Command; }
} /// <summary>
/// Creates an instance of CommandEventArgs class.
/// </summary>
/// <param name="cmd">The received command.</param>
public CommandEventArgs(CommandBase cmd)
{
m_Command = cmd;
}
} /// <summary>
/// Client event args.
/// </summary>
public class ClientEventArgs : EventArgs
{
}
}
EnumInstanceBuilder.csusing System;
using System.Reflection;namespace FBug.Framework.Communication
{/// <summary>
/// EnumUnitInstanceBuilder
/// </summary>
internal static class EnumInstanceBuilder
{
/// <summary>
///
/// </summary>
/// <param name="enumUnit"></param>
/// <param name="obj"></param>
/// <returns></returns>
internal static bool CreateInstance(Enum enumUnit, out object obj)
{
return EnumInstanceBuilder.CreateInstance(enumUnit.GetType(), enumUnit.ToString(), out obj);
} /// <summary>
///
/// </summary>
/// <param name="enumType"></param>
/// <param name="fieldItem"></param>
/// <param name="obj"></param>
/// <returns></returns>
internal static bool CreateInstance(Type enumType, string fieldItem, out object obj)
{
obj = null; Type cmdType;
object[] args; if (EnumInstanceBuilder.GetCommandType(enumType, fieldItem, out cmdType, out args))
{
if (args == null || args.Length == 0)
{
obj = Activator.CreateInstance(cmdType);
} obj = Activator.CreateInstance(cmdType, args);
return true;
} return false;
} /// <summary>
///
/// </summary>
/// <param name="enumType"></param>
/// <param name="type"></param>
/// <param name="args"></param>
/// <returns></returns>
private static bool GetCommandType(Type enumType, string fieldItem, out Type type, out object[] args)
{
type = null;
args = null; FieldInfo fieldInfo = enumType.GetField(fieldItem);
if (fieldInfo == null)
{
return false;
} object[] olist = fieldInfo.GetType().GetCustomAttributes(false);
foreach (object o in olist)
{
InstanceAttribute attr = o as InstanceAttribute;
if (attr != null)
{
type = attr.InstanceType;
args = attr.Args; return true;
}
} return false;
}
}
}
InstanceAttribute.csusing System;namespace FBug.Framework.Communication
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class InstanceAttribute : Attribute
{
/// <summary>
/// 实例对象类型
/// </summary>
public Type InstanceType { get; set; } /// <summary>
/// 实例默认参数
/// </summary>
public object[] Args { get; set; }
}
}
public Form1()
{
InitializeComponent(); CheckForIllegalCrossThreadCalls = false; LocalEPServer = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //开启线程
Thread th = new Thread(new ThreadStart(listen));
th.IsBackground = true;
th.Start();
} private void listen()
{
sListener.Bind(LocalEPServer);
sListener.Listen(10);
byte[] buffer = new byte[1024]; while (true)
{
sListener.Accept();
int byteRec = sListener.Receive(buffer);
byte[] ActualByte = new byte[byteRec];
Array.Copy(buffer, 0, ActualByte, 0, byteRec);
string ccc = System.Text.UnicodeEncoding.Unicode.GetString(buffer);
textBox1.Text += ccc + "\n\r";
}
}sListener.Receive(buffer); 这一句报错:
由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
/// <summary>
/// 后台监听。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DoWork_StartListening(object sender, DoWorkEventArgs e)
{
try
{
this.Socket.Listen(32);
m_IsListening = true;
}
catch (SocketException)
{
e.Cancel = true;
return;
} while (m_IsListening)
{
if (m_Listener.CancellationPending)
{
e.Cancel = true;
return;
} Socket clientSocket = null;
try
{
clientSocket = m_Socket.Accept();
}
catch
{
e.Cancel = true;
break;
} this.AddConnectedClient(clientSocket);
}
}
/// <summary>
/// 添加一个新的客户端连接
/// </summary>
/// <param name="socket"></param>
private void AddConnectedClient(Socket socket)
{
lock (this)
{
if (!m_IsListening)
{
return;
} ClientManager client = new ClientManager(socket);
client.CommandReceived += new CommandReceivedEventHandler(client_CommandReceived);
client.Disconnected += new EventHandler(client_Disconnected);
client.CommunicationTimeout = this.Timeout;
m_Clients.Add(
string.Format(c_IpAddressFormat, client.RemoteIpAddress, client.RemotePort),
client
);
}
}
{
sListener.Accept();
int byteRec = sListener.Receive(buffer);
byte[] ActualByte = new byte[byteRec];
Array.Copy(buffer, 0, ActualByte, 0, byteRec);
string ccc = System.Text.UnicodeEncoding.Unicode.GetString(buffer);
textBox1.Text += ccc + "\n\r";
}socket.Accept()会创建一个新的Socket。这个Socket装门用来和客户端通讯,而原先的socket还是继续保持监听。职能不同。
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;namespace FBug.Framework.Communication.Client
{
using DeployCommandBasic = FBug.Framework.Communication.DeployCommand; /// <summary>
/// 远程客户端
/// </summary>
public class ClientManager : IDisposable
{
#region override class CommunicatorExender
/// <summary>
/// 重载数据接收过程。
/// </summary>
private class CommunicatorExender : Communicator
{
/// <summary>
///
/// </summary>
/// <param name="socket"></param>
public CommunicatorExender(Socket socket, object owner) : base(socket, owner) { } /// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="cmds"></param>
/// <returns></returns>
protected override bool OnNetworkStreamReceiving(NetworkStream stream, out List<CommandBase> cmds)
{
cmds = null; if (!stream.DataAvailable)
{
return false;
} List<CommandBase> list = new List<CommandBase>();
DeployCommandBasic command;
while (DeployCommand.CreateCommand(stream, out command))
{
this.OnCommandReceived(new CommandEventArgs(command)); list.Add(command);
} if (list.Count > 0)
{
cmds = list;
return true;
} return false;
}
}
#endregion
#region Properties
/// <summary>
/// 消息收发者
/// </summary>
protected Communicator m_Communicator;
/// <summary>
/// 是否已连接到客户端。
/// </summary>
public bool Connected
{
get { return m_Communicator.Connected; }
} /// <summary>
/// 关闭前的数据发送延时
/// </summary>
public int LingerSecond
{
get { return m_Communicator.LingerSecond; }
set { m_Communicator.LingerSecond = value; }
} /// <summary>
/// 最后接收到得指令
/// </summary>
public List<CommandBase> LastReceivedCommands
{
get { return m_Communicator.LastSynReceivedCommands; }
} /// <summary>
/// 接收到Command后的处理
/// </summary>
public event CommandReceivedEventHandler CommandReceived
{
add { m_Communicator.CommandReceived += value; }
remove { m_Communicator.CommandReceived -= value; }
} /// <summary>
/// 连接断开后的处理
/// </summary>
public event EventHandler Disconnected
{
add { m_Communicator.Disconnected += value; }
remove { m_Communicator.Disconnected -= value; }
}
#endregion
#region constractor
/// <summary>
/// 初始化m_Communicator
/// </summary>
private void Initinal()
{
// m_Communicator.BufferReceived += new BufferReceivedEventHandler(Communicator_BufferReceived);
m_Communicator.CommandReceived += new CommandReceivedEventHandler(Communicator_CommandReceived);
}
/// <summary>
/// 创建已连接的客户端管理
/// </summary>
protected ClientManager(Socket socket)
{
m_Communicator = new CommunicatorExender(socket, this); this.Initinal();
}
/// <summary>
/// 创建客户端
/// </summary>
public ClientManager(string ip, int serverPort) : this(IPAddress.Parse(ip), serverPort) { }
/// <summary>
/// 创建客户端
/// </summary>
public ClientManager(IPAddress ip, int serverPort)
{
m_Communicator = Communicator.CreateClientCommunication<CommunicatorExender>(this, ip, serverPort); this.Initinal();
}
#endregion
#region Pulibc Method
/// <summary>
/// 开始接收
/// </summary>
public void StartReceiving()
{
m_Communicator.StartReceiving();
} /// <summary>
/// 停止接收
/// </summary>
public void StopReceiving()
{
m_Communicator.StopReceiving();
} /// <summary>
/// 同步发送指令
/// </summary>
/// <param name="buffer"></param>
public List<CommandBase> SendCommand(byte[] buffer)
{
return m_Communicator.SendCommand(buffer);
}
/// <summary>
/// 同步发送指令
/// </summary>
/// <param name="buffer"></param>
public List<CommandBase> SendCommand(CommandBase cmd)
{
return m_Communicator.SendCommand(cmd);
} /// <summary>
/// 同步发送指令列表
/// </summary>
/// <param name="cmds"></param>
/// <returns></returns>
public List<CommandBase> SendCommand(List<CommandBase> cmds)
{
List<byte> buffer = new List<byte>();
foreach (CommandBase cmd in cmds)
{
buffer.AddRange(cmd.ToByties());
} return this.SendCommand(buffer.ToArray());
}
#endregion
#region private method
/// <summary>
/// 当接收到消息时候的处理(draft)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Communicator_BufferReceived(object sender, BufferEventArgs e)
{
int startIndex = 0;
for (int i = 0; i < e.Byties.Length; i++)
{
if (e.Byties[i].Equals((byte)DeployCommandBasic.c_Split_End))
{
DeployCommandBasic cmd;
if (DeployCommand.CreateCommand(e.Byties, startIndex, i - startIndex + 1, out cmd))
{
e.Commands.Add(cmd);
} startIndex = i + 1;
}
}
} /// <summary>
/// 接收到命令后的处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Communicator_CommandReceived(object sender, CommandEventArgs e)
{
switch ((CommandTyies)Enum.Parse(typeof(CommandTyies), e.Command.CommandType))
{
case CommandTyies.OK:
break;
case CommandTyies.XE:
break;
case CommandTyies.XK:
break;
default:
break;
}
}
#endregion
#region IDisposable Members
/// <summary>
///
/// </summary>
private bool m_Disposed = false;
/// <summary>
///
/// </summary>
/// <param name="dispossing"></param>
protected virtual void Dispose(bool dispossing)
{
if (m_Disposed)
{
return;
} if (dispossing)
{
this.StopReceiving();
} m_Disposed = true;
}
/// <summary>
/// 停止监听,并销毁实例。
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
FBug.Framework.Communication.Server名字空间种的ClientManager的是继承与Client名字空间下面的ClientManager,其功能大同小异。
public Form1()
{
InitializeComponent(); CheckForIllegalCrossThreadCalls = false; LocalEPServer = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //开启线程
Thread th = new Thread(new ThreadStart(listen));
th.IsBackground = true;
th.Start();
//handler = Connect(ref handler);
} private void listen()
{
sListener.Bind(LocalEPServer);
sListener.Listen(10);
byte[] buffer = new byte[8192]; while (true)
{
int byteRec = sListener.Receive(buffer);
byte[] ActualByte = new byte[byteRec];
Array.Copy(buffer, 0, ActualByte, 0, byteRec);
string ccc = System.Text.UnicodeEncoding.Unicode.GetString(buffer);
textBox1.Text += ccc + "\n\r";
}
}
处理一个客户端发送过来的字符串而已,sListener.Receive(buffer) 这一句报错:由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
你看这个过程: private void DoWork_StartListening(object sender, DoWorkEventArgs e)
{
try
{
this.Socket.Listen(32);
m_IsListening = true;
}
catch (SocketException)
{
e.Cancel = true;
return;
} while (m_IsListening)
{
if (m_Listener.CancellationPending)
{
e.Cancel = true;
return;
} Socket clientSocket = null;
try
{
clientSocket = m_Socket.Accept();
}
catch
{
e.Cancel = true;
break;
} this.AddConnectedClient(clientSocket);
}
}
m_Listener 就是你的那个sListener。 我根本没使用它来做接收数据(他是只用来监听的)。
clientSocket = m_Socket.Accept();
获得了这个clientSocket后, Receive数据的是这个clientSocket。(而不是m_Listener)再看你写的:sListener.Receive(buffer);
这些东西是要你自己去做比较的,我直接帮你改好了你还是不懂,自己摸索了就会了的
private void listen()
{
sListener.Bind(LocalEPServer);
sListener.Listen(10);
byte[] buffer = new byte[1024]; while (true)
{
Socket newsocket = sListener.Accept();//用接受到的Socket来收发数据
int byteRec = newsocket.Receive(buffer);
//byte[] ActualByte = new byte[byteRec];
//Array.Copy(buffer, 0, ActualByte, 0, byteRec);
string ccc = Encoding.Unicode.GetString(buffer,0,byteRec);
textBox1.Text += ccc + "\n\r";
}
}
还有,我也是近半个月以来才开始写TCP,上面的框架也是我的构想,可能某些地方还需完善。
{
Socket newsocket = sListener.Accept(); 执行到这里,再按F11,不能进行调试,直接就运行了。
另外实际在客户端写接受请求基本上不用那个Accept()方法,用得最多的是BeginAccept()方法,也可以用新的方法AcceptAsync(SocketAsyncEventArgs e),这两种方法都是异步接受请求的,异步接受请求可以让接受连接请求的线程独立出来,不至于阻塞新连接的数据收发。至于详细资料,可以参考MSDN,我摘取一段完整的服务器段代码你看看。using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() {
} public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp ); // Bind the socket to the local endpoint and listen for incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100); while (true) {
// Set the event to nonsignaled state.
allDone.Reset(); // Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener ); // Wait until a connection is made before continuing.
allDone.WaitOne();
} } catch (Exception e) {
Console.WriteLine(e.ToString());
} Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
} public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set(); // Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar); // Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
} public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket; // Read data from the client socket.
int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead)); // Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
} private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState; // Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both);
handler.Close(); } catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args) {
StartListening();
return 0;
}
}
Socket newsocket = sListener.Accept();方法会产生阻塞。必须等到有新连接后才会继续执行,并返回这个newsocket。
tcp是支持多连接的,你想想rpg游戏,一群客户端,连接的都是同一个端口,
每一位客户端,都会分配一个newsocket与之通讯。
还要解析字节多麻烦。