今天被迫要做一个接收通信的模块,以前从来都没有做过关于通信方面的东西,就像没有做过有关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文件中的代码:

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文件中的代码:

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文件中的代码:

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文件中的代码:

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文件中的代码:

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;
}
}
}
}
(6)、Server.cs文件中的代码:

Server.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();
}