• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

一个有用的Windows服务小程序——用来完成Server端的Socket通信[转载]-beeone ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
 今天被迫要做一个接收通信的模块,以前从来都没有做过关于通信方面的东西,就像没有做过有关GIS方面的程序一样是头一次开发此类程序。
      这个Socket通信说是自己的其实完全不是(如果哪位高人见到此程序是您本人开发的千万不要介意,本人也是在网上搜索出的,这个程序真的很不错,值得推广哦!在此谢谢发布此Socket通信程序的高人)。
      此程序的大部分源码没有任何改动,只是原来的Server端是用C/S程序写的,为了能使Socket通信的Server端更灵活,在此将其改成一个Windows服务,因此也需要改动了一些Server端的代码和工程,但是基础类和Client端都没有改变。
      对于我本人来说,Windows服务和Socket通信本人都不是很了解,只是经过了昨天简单的学习和研究才完成了此Windows服务Server端Socket通信程序,所以也说不出太多的门道,如果有清楚这方面知识的博友还希望能多多交流。好了,废话少说,开始正题了。
      现在开始我们来讲解,如何一步一步地完成Windows服务Server端Socket通信程序。
      我个人认为Windows服务只是包裹在Socket通信程序外的“一件外套”,所以核心还是我在网上找到的这个Socket程序,为此我们的第一步应该先开发出此Socket程序的类库。
1、打开Visual Studio.Net2003,单击菜单中的“文件”——>“新建”——>“项目”,在弹出的对话框左侧选择“Visual C#项目”,在右侧选择“类库”,下方的名称中输入“SocketLibrary”,位置自己随便选择一个路径。
2、删除自动创建的Class1.cs,新建如下的类名文件“Client.cs”、“Connection.cs”、“ConnectionCollection.cs”、“Message.cs”、“MessageCollection.cs”、“Server.cs”、“SocketBase.cs”和“SocketFactory.cs”。
3、各个类文件的代码如下:
(1)、Client.cs文件中的代码:
using System;
using System.Net;
using System.Net.Sockets;

namespace SocketLibrary
{

public class Client:SocketBase
{
public const int CONNECTTIMEOUT = 10;
public Client()
{

}
public Connection StartClient(IPAddress ipaddress,int port) {
TcpClient client
= new TcpClient();
client.SendTimeout
= CONNECTTIMEOUT;
client.ReceiveTimeout
= CONNECTTIMEOUT;

client.Connect(ipaddress,port);

this._connections.Add(new Connection(client.GetStream()));
this.StartListenAndSend();
return new Connection(client.GetStream());
}
public void StopClient() {


this.EndListenAndSend();
}
}
}
(2)、Connection.cs文件中的代码:
using System;
using System.Net;
using System.Net.Sockets;

namespace SocketLibrary
{
/**//// <summary>
/// Connection 的摘要说明。
/// </summary>
public class Connection
{
public NetworkStream NetworkStream {
get{return _networkStream;}
set{_networkStream = value;}
}
private NetworkStream _networkStream;
public string ConnectionName {
get{return _connectionName;}
set{_connectionName = value;}
}
private string _connectionName;
public Connection(NetworkStream networkStream,string connectionName)
{
this._networkStream = networkStream;
this._connectionName = connectionName;
}
public Connection(NetworkStream networkStream):this(networkStream,string.Empty) {
}
}
}
(3)、ConnectionCollection.cs文件中的代码:
using System;

namespace SocketLibrary {
public class ConnectionCollection:System.Collections.CollectionBase {
public ConnectionCollection() {

}
public void Add(Connection value) {
List.Add(value);
}
public Connection this[int index] {
get {
return List[index] as Connection;
}
set{
List[index]
= value;
}
}
public Connection this[string connectionName] {
get {
foreach(Connection connection in List) {
if(connection.ConnectionName == connectionName)
return connection;
}
return null;
}
}
}
}
(4)、Message.cs文件中的代码:
using System;

namespace SocketLibrary
{
public class Message
{
public enum CommandHeader:byte {
SendMessage
= 1
}
public Connection SendToOrReceivedFrom;
public int MessageLength;
public CommandHeader Command;
public byte MainVersion;
public byte SecondVersion;

public string MessageBody;

public bool Sent;

public Message()
{
SendToOrReceivedFrom
= null;
Sent
= false;
}
public Message(CommandHeader command,byte mainVersion,byte secondVersion,string messageBody):this() {
this.Command = command;
this.MainVersion = mainVersion;
this.SecondVersion = secondVersion;
this.MessageBody = messageBody;
}
public byte[] ToBytes() {
this.MessageLength = 7 + SocketFactory.DefaultEncoding.GetByteCount(this.MessageBody);//计算消息总长度。消息头长度为7加上消息体的长度。
byte[] buffer = new byte[this.MessageLength];
//先将长度的4个字节写入到数组中。
BitConverter.GetBytes(this.MessageLength).CopyTo(buffer,0);
//将CommandHeader写入到数组中
buffer[4] = (byte)this.Command;
//将主版本号写入到数组中
buffer[5] = (byte)this.MainVersion;
//将次版本号写入到数组中
buffer[6] = (byte)this.SecondVersion;

//消息头已写完,现在写消息体。
byte[] body = new byte[this.MessageLength - 7];
SocketFactory.DefaultEncoding.GetBytes(
this.MessageBody).CopyTo(buffer,7);
return buffer;
}
public static Message Parse(Connection connection) {
Message message
= new Message();
//先读出前四个字节,即Message长度
byte[] buffer = new byte[4];
if(connection.NetworkStream.DataAvailable) {
int count = connection.NetworkStream.Read(buffer,0,4);
if(count == 4) {
message.MessageLength
= BitConverter.ToInt32(buffer,0);
}
else
throw new Exception("网络流长度不正确");
}
else
throw new Exception("目前网络不可读");
//读出消息的其它字节
buffer = new byte[message.MessageLength - 4];
if(connection.NetworkStream.DataAvailable) {
int count = connection.NetworkStream.Read(buffer,0,buffer.Length);
if(count == message.MessageLength -4) {
message.Command
= (CommandHeader)buffer[0];
message.MainVersion
= buffer[1];
message.SecondVersion
= buffer[2];

//读出消息体
message.MessageBody = SocketFactory.DefaultEncoding.GetString(buffer,3,buffer.Length - 3);
message.SendToOrReceivedFrom
= connection;

return message;
}
else
throw new Exception("网络流长度不正确");
}
else
throw new Exception("目前网络不可读");
}

}
}
(5)、MessageCollection.cs文件中的代码:
using System;

namespace SocketLibrary
{
public class MessageCollection:System.Collections.CollectionBase
{
public MessageCollection()
{

}
public void Add(Message value) {
List.Add(value);
}
public Message this[int index] {
get {
return List[index] as Message;
}
set{
List[index]
= value;
}
}
public MessageCollection this[Connection connection] {
get {
MessageCollection collection
= new MessageCollection();
foreach(Message message in List) {
if(message.SendToOrReceivedFrom == connection)
collection.Add(message);
}
return collection;
}
}
}
}
(7)、SocketBase.cs文件中的代码:
using System;
using System.Net;
using System.Net.Sockets;

namespace SocketLibrary
{
public class Server:SocketBase
{


private TcpListener _listener;
public Server()
{
this._connections = new ConnectionCollection();
}
protected System.Threading.Thread _listenConnection;

public void StartServer(int port) {
_listener
= new TcpListener(IPAddress.Any, port);
_listener.Start();

_listenConnection
= new System.Threading.Thread(new System.Threading.ThreadStart(Start));
_listenConnection.Start();

this.StartListenAndSend();
}
public void StopServer() {
_listenConnection.Abort();
this.EndListenAndSend();

}
private void Start() {
try {
while(true) {
if(_listener.Pending()) {
TcpClient client
= _listener.AcceptTcpClient();
NetworkStream stream
= client.GetStream();
Connection connection
= new Connection(stream);
this._connections.Add(connection);
this.OnConnected(this,new ConnectionEventArgs(connection,new Exception("连接成功")));
}
System.Threading.Thread.Sleep(
200);
}
}
catch {
}
}

}
}
(7)、SocketBase.cs文件中的代码:
using System;

namespace SocketLibrary
{
/**//// <summary>
/// SocketBase 的摘要说明。
/// </summary>
public class SocketBase
{
public class MessageEventArgs:EventArgs {
public Message Message;
public Connection Connecction;
public MessageEventArgs(Message message,Connection connection) {
this.Message = message;
this.Connecction = connection;
}
}
public delegate void MessageEventHandler(object sender,MessageEventArgs e);

public class ConnectionEventArgs:EventArgs {
public Connection Connection;
public Exception Exception;
public ConnectionEventArgs(Connection connection,Exception exception) {
this.Connection = connection;
this.Exception = exception;
}
}
public delegate void ConnectionHandler(object sender,ConnectionEventArgs e);

public ConnectionCollection Connections {
get{return _connections;}
set{_connections = value;}
}
protected ConnectionCollection _connections;

public MessageCollection messageQueue {
get{return _messageQueue;}
set{_messageQueue = value;}
}
protected MessageCollection _messageQueue;

public SocketBase()
{
this._connections = new ConnectionCollection();
this._messageQueue = new MessageCollection();
}
protected void Send(Message message) {
this.Send(message,message.SendToOrReceivedFrom);
}
protected void Send(Message message,Connection connection) {
byte[] buffer = message.ToBytes();
lock(this) {
connection.NetworkStream.Write(buffer,
0,buffer.Length);
}
}

protected System.Threading.Thread _listenningthread;
protected System.Threading.Thread _sendthread;
protected virtual void Sendding() {
try {
while(true) {
System.Threading.Thread.Sleep(
200);
for(int i = 0 ; i < this.messageQueue.Count ; i++) {
if(this.messageQueue[i].SendToOrReceivedFrom != null) {
this.Send(this.messageQueue[i]);
this.OnMessageSent(this,new MessageEventArgs(this.messageQueue[i],this.messageQueue[i].SendToOrReceivedFrom));
}
else {//对每一个连接都发送此消息
for(int j = 0 ; j < this.Connections.Count ; j++) {
this.Send(this.messageQueue[i],this.Connections[j]);
this.OnMessageSent(this,new MessageEventArgs(this.messageQueue[i],this.Connections[j]));
}
}
this.messageQueue[i].Sent = true;
}
//清除所有已发送消息
for(int i = this.messageQueue.Count - 1 ; i > -1 ; i--) {
if(this.messageQueue[i].Sent)
this.messageQueue.RemoveAt(i);
}
}
}
catch{
}
}
protected virtual void Listenning() {
try {
while(true) {
System.Threading.Thread.Sleep(
200);
foreach(Connection connection in this._connections) {
if(connection.NetworkStream.CanRead && connection.NetworkStream.DataAvailable) {
try {
Message message
= Message.Parse(connection);
this.OnMessageReceived(this,new MessageEventArgs(message,connection));
}
catch(Exception ex) {
connection.NetworkStream.Close();
this.OnConnectionClose(this,new ConnectionEventArgs(connection,ex));
}
}
}
}
}
catch {
}
}

protected void StartListenAndSend() {
_listenningthread
= new System.Threading.Thread(new System.Threading.ThreadStart(Listenning));
_listenningthread.Start();
_sendthread
= new System.Threading.Thread(new System.Threading.ThreadStart(Sendding));
_sendthread.Start();
}
public void EndListenAndSend() {
_listenningthread.Abort();
_sendthread.Abort();
}



public event MessageEventHandler MessageReceived;
public event MessageEventHandler MessageSent;
public event ConnectionHandler ConnectionClose;
public event ConnectionHandler Connected;

public void OnMessageReceived(object sender,MessageEventArgs e) {
if(MessageReceived != null)
this.MessageReceived(sender,e);
}
public void OnMessageSent(object sender,MessageEventArgs e) {
if(MessageSent != null)
this.MessageSent(sender,e);
}
public void OnConnectionClose(object sender,ConnectionEventArgs e) {
if(ConnectionClose != null)
this.ConnectionClose(sender,e);
}
public void OnConnected(object sender,ConnectionEventArgs e) {
if(Connected != null)
this.Connected(sender,e);
}
}
}
(8)、SocketFactory.cs文件中的代码:
using System;
using System.Net;
using System.Net.Sockets;

namespace SocketLibrary {
/**////

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
小程序mdns+udpSocket实现电视推送发布时间:2022-07-18
下一篇:
微信小程序获得unionid发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap