Socket类为网络通讯提供了一套丰富的方法和属性。
Socket允许使用ProtocolType枚举中所列出的任何一种协议执行同步和异步数据传输。如果需要使用较为简单的应用程序,而且不需要太高的性能。建议使用UdpClient和TcpClient、TcpListener。
一般说来Tcp通讯包含:服务端与客户端两部分。下面我从一个类似聊天室的程序来阐述基于Socket的Tcp通讯。下一章节,我将会阐述UDP通讯。
在调用Scoket类的方法时,必须先对Socket类使用指定的地址簇,套接字类型和协议初始化Socket类的新实例。
Socket ServerSK = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
针对服务端,使用Socket与一个本地的终结点相关联。
IPEndPoint endIpInfo = new IPEndPoint(IPAddress.Parse(Ip),port);
ServerSK.Bind(endIpInfo );
关联终结点后,需要把Socket置于侦听的状态。
ServerSK.Listen(50);
Listen 的参数是指侦听队列的长度。在侦听之前必须调用Bind方法,否则将会引发异常。
调用Accept方法会以同步的方式侦听套接字的连接请求队列中第一个被挂起的连接请求,然后创建并返回新的Socket。
ClientSK[ClientNum] = ServerSK.Accept();
Socket的RemoteEndPoint方法可标识远程连接的端口号及网络地址。
调用新建的Socket对象的BeginReceive方法可开始从连接的Socket中异步的接受数据。(此方法必须有EndReceive方法与之对应)
ClientSK[ClientNum].BeginReceive(refBuffer ,0,refBuffer.Length,0,new AsyncCallback(ReceiveCallBack),ClientSK[ClientNum]);
在接受数据时,可调用 AsyncCallback 委托来引用操作完成时需要调用的方法。此异步操作的方式可实现IAsyncResult 接口。
调用连接的Socket的sned或SendTo发放将数据发送到远程终端主机。
对于客户端来说,只是调用Connet方法来建立与远程主机的连接。
源码附上,不再鳌述。更多方法还请读者自己实践。
服务端源码:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text.RegularExpressions;
using System.Collections;
namespace ServerEnd
{
public class Service
{
#region 变量
IPEndPoint endIpInfo;//所要开放的服务器Ip与端口
Socket ServerSK; //服务端Socket
Socket[] ClientSK;//客户端Socket
byte[] refBuffer;//数据缓冲区
byte[] sendBuffer;
int ClientNum;//存放连接的客户端数量
Thread sThread; //服务端运行的线程
string sfIp;
ArrayList arr = new ArrayList();//记录当前连接的IP
#endregion
//声明委托类型
public delegate void ReceiveMsgHandle(object sender,Msg message);
//定义事件
public event ReceiveMsgHandle ReceiveMsg;
/// <summary>
/// 构造函数初始化服务器IP及端口
/// </summary>
/// <param name="Ip"></param>
/// <param name="port"></param>
public Service(string Ip,int port)
{
sfIp = Ip;
endIpInfo = new IPEndPoint(IPAddress.Parse(Ip),port);
refBuffer = new byte[65535];
sendBuffer = new byte[65535];
ClientSK = new Socket[65535];
ClientNum = 0;
}
/// <summary>
/// 开启服务端
/// </summary>
public void StartConn()
{
ServerSK = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSK.Bind(endIpInfo);
ServerSK.Listen(50);
sThread = new Thread(ServerProcess);
sThread.IsBackground = true;
sThread.Start();
}
/// <summary>
/// 开启监听
/// </summary>
private void ServerProcess()
{
try
{
while (true)
{
ClientSK[ClientNum] = ServerSK.Accept();
//记录连接的IP
arr.Add(((IPEndPoint)ClientSK[ClientNum].RemoteEndPoint).Address.ToString());
ClientSK[ClientNum].BeginReceive(refBuffer ,0,refBuffer.Length,0,new AsyncCallback(ReceiveCallBack),ClientSK[ClientNum]);
ClientNum++;
}
}
catch { }
}
/// <summary>
/// 一个 AsyncCallback 委托,它引用操作完成时要调用的方法
/// </summary>
/// <param name="ar"></param>
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
Socket rSocket = (Socket)ar.AsyncState;
int Rnd = rSocket.EndReceive(ar);
string str = Encoding.Default.GetString(refBuffer);
if (IPCheck(ip))
{
for (int i = 0; i < ClientNum; i++)
{
IPEndPoint endIp = (IPEndPoint)ClientSK[i].RemoteEndPoint;
if (ip.Equals(endIp.Address.ToString()))
{
ClientSK[i].Send(refBuffer, 0, Rnd, 0);
break;
}
else if (ip.Equals(sfIp))
{
Msg message = new Msg();
message.Message = str ;
if (ReceiveMsg != null)
ReceiveMsg(this, message);//触发事件
}
}
}
rSocket.BeginReceive(refBuffer, 0, refBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), rSocket);
}
catch { }
}
/// <summary>
/// 验证IP
/// </summary>
/// <param name="IP"></param>
/// <returns></returns>
private bool IPCheck(string IP)
{
string num = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";
return Regex.IsMatch(IP, ("^" + num + "\\." + num + "\\." + num + "\\." + num + "$"));
}
/// <summary>
/// 关闭服务
/// </summary>
public void DisConn()
{
ServerSK.Close();
}
/// <summary>
/// 发送消息到已连接的客户端
/// </summary>
/// <param name="Ip"></param>
/// <param name="msg"></param>
public void SendMsg(string Ip,string msg)
{
try
{
sendBuffer = Encoding.Default.GetBytes(msg));
for (int i = 0; i < ClientNum; i++)
{
IPEndPoint endIp = (IPEndPoint)ClientSK[i].RemoteEndPoint;
if (Ip.Equals(endIp.Address.ToString()))
{
ClientSK[i].Send(sendBuffer);
break;
}
}
}
catch { }
}
}
}
客户端代码:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace ConnClient
{
public class ConClient
{
#region 变量
IPEndPoint endIpInfo;//连接服务端的IP与端口号
Socket clientSk; //客户端Socket
byte []refBuffer; //消息数据缓冲区
byte[] sendBuffer; //发送段数据
#endregion
//声明委托类型
public delegate void ReceiveMsgHandle(object sender,Msg message);
//定义接受到消息事件
public event ReceiveMsgHandle ReceiveMsg;
/// <summary>
/// 构造函数用来初始化服务端数据
/// </summary>
/// <param name="IP">服务端IP</param>
/// <param name="port">需要与服务端建立的端口号</param>
public ConClient(string IP,int port)
{
endIpInfo = new IPEndPoint(IPAddress.Parse(IP), port);
refBuffer = new byte[65535];
sendBuffer = new byte[65535];
}
/// <summary>
/// 连接服务端
/// </summary>
/// <returns></returns>
public bool StartConnet()
{
clientSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSk.Connect(endIpInfo);//连接服务器
if (clientSk.Connected == true)
{
clientSk.BeginReceive(refBuffer, 0, refBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
return true;
}
else
return false;
}
/// <summary>
/// 一个 AsyncCallback 委托,它引用操作完成时要调用的方法
/// </summary>
/// <param name="Ar"></param>
public void ReceiveCallBack(IAsyncResult Ar)
{
try
{
int Rnd = clientSk.EndReceive(Ar);
string msgg = Encoding.Default.GetString(refBuffer, 0, Rnd));
Msg message = new Msg();
message.Message = msgg ;
message.RefBuffer = refBuffer;
if (ReceiveMsg != null)
ReceiveMsg(this, message);//引发事件
clientSk.BeginReceive(refBuffer, 0, refBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
}
catch { }
}
/// <summary>
/// 关闭连接
/// </summary>
public void DisConn()
{
clientSk.Close();
}
/// <summary>
/// 向目的IP发送消息
/// </summary>
/// <param name="Ip">目的方IP</param>
/// <param name="Msg">消息内容</param>
public void SendMsg(string Ip,string Msg)
{
sendBuffer = Encoding.Default.GetBytes(Msg);
clientSk.Send(sendBuffer);
}
}
}
把源码也附上,各位可以参考。不足之处希望给予指点。
/Files/dwwwing/TcpCon.rar