让知识更加联贯
让技术走进生活
我的博客
我的程序
我的网络
------
郑紫至
E-mail:zhengzizhi@yahoo.com.cn
智能通道系统
本系统全面地展示了
Socket
与多线程,数据库,工业上采用的
CRC
查表校验信息码
等综合技术的完整代码,从代码的角度展示了工控通讯的完整过程,本系统可以改装成
地铁、火车站、海关、商场、旅游景点,智能小区、大型集团公司,大型停车场,
等等需要刷卡通行智能验证平台,本系统使用了软终端从理论的角度模拟出单片机终
端设备的通讯过程。
开发工具
:Visual Studio 2008.NET(C#) + Microsoft SQL Server 2005
智能通道系统之
(1)Server
1
.设计模式下的界面截图
2
.
MainForm.cs
:
//******************************************************************************************
//
作者 :郑紫至
//
创建日期:2008-03-14
//
邮件地址:zhengzizhi@mail.china.com
//
博客地址:http://hi.csdn.net/zhengzizhi
//
备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//******************************************************************************************
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
System.Net;
using
System.Net.Sockets;
using
System.Threading;
using
System.Data.SqlClient;
using
System.Configuration;
namespace
Server
{
public partial class MainForm : Form
{
public static ListBox TopListBox;
public static ListBox MiddleListBox;
public static ListBox BottomListBox;
///<summary>
/// IsServerSocketRunning
默认为执行状态
///</summary>
bool IsServerSocketRunning = true;
public static PictureBox[] PictureBoxArray;
public static Label[] LabelArray;
public static PictureBox ConnectedPictureBox;
public static PictureBox DisconnectedPictureBox;
int ServerPromgramRunningSeconds = 0;
int MachineCount = 0;
Thread ThreadOfStartServerSocketListening;
Socket ServerSocket;
private Socket SocketOfNewlyConnection;
public MainForm()
{
InitializeComponent();
InitStaticListBoxes();
}
private void InitStaticListBoxes()
{
TopListBox = new ListBox();
MiddleListBox = new ListBox();
BottomListBox = new ListBox();
//
// TopListBox
//
TopListBox.BackColor = System.Drawing.Color.Black;
TopListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
TopListBox.Dock = System.Windows.Forms.DockStyle.Top;
TopListBox.Font = new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
TopListBox.ForeColor = System.Drawing.Color.Lime;
TopListBox.FormattingEnabled = true;
TopListBox.HorizontalScrollbar = true;
TopListBox.ItemHeight = 12;
TopListBox.Location = new System.Drawing.Point(3, 3);
TopListBox.Name = "TopListBox";
TopListBox.ScrollAlwaysVisible = true;
TopListBox.Size = new System.Drawing.Size(748, 170);
TopListBox.TabIndex = 4;
//
// MiddleListBox
//
MiddleListBox.BackColor = System.Drawing.Color.Black;
MiddleListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
MiddleListBox.Dock = System.Windows.Forms.DockStyle.Top;
MiddleListBox.Font = new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
MiddleListBox.ForeColor = System.Drawing.Color.Lime;
MiddleListBox.FormattingEnabled = true;
MiddleListBox.HorizontalScrollbar = true;
MiddleListBox.ItemHeight = 12;
MiddleListBox.Location = new System.Drawing.Point(4, 173);
MiddleListBox.Name = "MiddleListBox";
MiddleListBox.ScrollAlwaysVisible = true;
MiddleListBox.Size = new System.Drawing.Size(747, 170);
MiddleListBox.TabIndex = 5;
//
// BottomListBox
//
BottomListBox.BackColor = System.Drawing.Color.Black;
BottomListBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
BottomListBox.Dock = System.Windows.Forms.DockStyle.Fill;
BottomListBox.Font = new System.Drawing.Font("PMingLiU", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(136)));
BottomListBox.ForeColor = System.Drawing.Color.Lime;
BottomListBox.FormattingEnabled = true;
BottomListBox.HorizontalScrollbar = true;
BottomListBox.ItemHeight = 12;
BottomListBox.Location = new System.Drawing.Point(5, 343);
BottomListBox.Name = "BottomListBox";
BottomListBox.ScrollAlwaysVisible = true;
BottomListBox.Size = new System.Drawing.Size(746, 182);
BottomListBox.TabIndex = 7;
TopListBox.Parent = this.tabPage2;
MiddleListBox.Parent = this.tabPage2;
BottomListBox.Parent = this.tabPage2;
this.tabPage2.Parent = this.tabControl1;
}
#region
CRC16 Table Polynomial = 0xA001
byte[] CrcTableH8bit = {0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,
0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,
0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,
0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,
0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,
0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,
0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,
0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,
0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,
0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,
0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,
0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,
0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,
0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,
0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,
0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40};
byte[] CrcTableL8bit = {0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40};
#endregion
///<summary>
///
根据卡机数目初始化客户端卡机处于“断开状态”图片和卡机编号
///</summary>
///<param name="MachineCount">
卡机数目
</param>
public void InitMachineImage(int MachineCount)
{
PictureBoxArray = new PictureBox[MachineCount + 1];
LabelArray = new Label[MachineCount + 1];
for ( int i = 1; i <= MachineCount; i++)
{
PictureBoxArray[i] = new PictureBox();
PictureBoxArray[i].Parent = this.ListViewImageConnectingStatus;
//
获得客户端卡机断开与服务连接的“断开状态”图片
PictureBoxArray[i].Image = this.imageList1.Images[0];
PictureBoxArray[i].Left = 2 + 50 * (i - 1);
PictureBoxArray[i].Top = 3;
PictureBoxArray[i].SizeMode = PictureBoxSizeMode.AutoSize;
PictureBoxArray[i].Visible = true;
LabelArray[i] = new Label();
LabelArray[i].Parent = this.ListViewImageConnectingStatus;
LabelArray[i].Text = (i).ToString() + "
号"
;
LabelArray[i].ForeColor = Color.Blue;
LabelArray[i].Left = 2 + (i - 1) * 50;
LabelArray[i].Top = 36;
LabelArray[i].Visible = true;
LabelArray[i].AutoSize = true;
}
}
///<summary>
///
以查表法获得需要校验字节信息的16进制CRC码
///
表格数据的生成多项式CRC-16 Polynomial = 0xA001
///</summary>
///<param name="RequestToCheckBytes">
需要校验的字节数组
</param>
///<param name="RequestToCheckLengthOfBytes">
实际传入的字节数长度
</param>
///<returns>
返回一个高两位在前,低两位在后的16进制CRC码
</returns>
public string HexCrcCode(byte[] RequestToCheckBytes, int RequestToCheckLengthOfBytes)
{
int CrcTableIndex = 0;
byte CrcH8bit = 0x00, CrcL8bit = 0x00;
for (int i = 0; i < RequestToCheckLengthOfBytes; i++)
{
if (RequestToCheckBytes[i] >= 0 && RequestToCheckBytes[i] < 255)
{
CrcTableIndex = RequestToCheckBytes[i] ^ CrcL8bit;
CrcL8bit = (byte)(CrcTableL8bit[CrcTableIndex] ^ CrcH8bit);
CrcH8bit = CrcTableH8bit[CrcTableIndex];
}
}
return CrcH8bit.ToString("x2").ToUpper() + CrcL8bit.ToString("x2").ToUpper();
}
public static IPAddress GetServerIP()
{
IPHostEntry ieh = Dns.GetHostEntry(Dns.GetHostName());// Dns.GetHostByName(Dns.GetHostName();
return ieh.AddressList[0];
}
public CardMachineCollection CardMachineList = new CardMachineCollection();
///<summary>
///
当服务器Socket实例_ServerSocket[它是SocketOfNewlyConnection赋给的值]收到的字节长度大于42个字节
///
并且OnReceiveData事件非null值时,触发事件要执行的方法CardMachine_OnReceiveData()
///</summary>
///<param name="sender">
当前类的实例
</param>
///<param name="ReceiveString">
服务器接收到的字符串(由服务器接收到的字节转变而来)
</param>
///<param name="ReceiveStringLength">
服务器接收到的字符串长度
</param>
///<param name="ReceiveBytes">
服务器接收到的字节
</param>
private void CardMachine_OnReceiveData(object sender, string ServerReceivedString, int ServerReceivedStringLength, byte[] ServerReceivedBytes)
{
try
{
string CardNo = string.Empty;
string MachineNo = string.Empty;
string ReadHeadNo = string.Empty;
string SendToClientString = string.Empty;
string EmpNo = string.Empty;
string EmpName = string.Empty;
string CardPassingState = string.Empty;
string PassingTime = string.Empty;
string PassingStateInfo = string.Empty;
if (ServerReceivedString.IndexOf("<EOF>") > -1)
{
(sender as CardMachine).Close();
}
if (ServerReceivedBytes[0] == 0x03 && (ServerReceivedStringLength == 43))
{
//
从第0位到第42位(长度为43)这段字符串中截取第19位20位21位22位23位24位25位和第26位表示卡号的字串
CardNo = Convert.ToInt32(ServerReceivedString.Substring(19, 8), 16).ToString();
//
卡号不足10位左边补0,直到满足10位退出循环
while (CardNo.Length < 10)
{
CardNo = "0" + CardNo;
}
//
从第0位到第42位(长度为43)这段字符串中截取第1位和第2位表示卡机编号的字串
MachineNo = ServerReceivedString.Substring(1, 2);
//
从第0位到第42位(长度为43)这段字符串中截取第5位和第6位表示卡机读头编号的字串
ReadHeadNo = ServerReceivedString.Substring(5, 2);
}
if ( !string.IsNullOrEmpty(CardNo))
{
if ((sender as CardMachine).SqlConn.State != ConnectionState.Open)
{
(sender as CardMachine).SqlConn.Open();
}
(sender as CardMachine).SqlComm.Parameters["@CardNo"].Value = CardNo;
(sender as CardMachine).SqlComm.Parameters["@MachineNo"].Value = MachineNo;
(sender as CardMachine).SqlComm.Parameters["@ReadHeadNo"].Value = Convert.ToInt32(ReadHeadNo);
(sender as CardMachine).SqlComm.ExecuteNonQuery();
EmpNo = (sender as CardMachine).SqlComm.Parameters["@EmpNo"].Value.ToString();
EmpName = (sender as CardMachine).SqlComm.Parameters["@EmpName"].Value.ToString();
CardPassingState = (sender as CardMachine).SqlComm.Parameters["@CardPassingState"].Value.ToString();
PassingTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
switch (CardPassingState)
{
case "0": PassingStateInfo = "
正常通行"
; break;
case "1": PassingStateInfo = "
无效卡号"
; break;
case "2": PassingStateInfo = "
未到或已过就餐时间"
; break;
case "3": PassingStateInfo = "
无设置就餐时段"
; break;
}
//
非正常通行时
if (CardPassingState != "0")
{
//
发送到客户端卡机的字符串(卡机读头编号固定为04)
SendToClientString = Convert.ToChar(0x01) + MachineNo + "JA" + "04" + Convert.ToChar(0x02);
//
将字符串转换成字节数组,以获得16进制CRC校验码
byte[] SendToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//
信息码+16进制CRC校验码+换行符
SendToClientString = SendToClientString + HexCrcCode(SendToClientBytes, 8) + Convert.ToChar(0x0D);
//
将字符串转换成字节数组
byte[] SendingToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//
将字节数组发送到客户端的卡机
(sender as CardMachine).SavedSocketOfNewlyConnected.Send(SendingToClientBytes);
}
else
{
//
发送到客户端卡机的字符串(读头编号是客户端卡机发送过来的43位字符串中包含的)
SendToClientString = Convert.ToChar(0x01) + MachineNo + "JA" + ReadHeadNo + Convert.ToChar(0x02);
//
将字符串转换成字节数组,以获得16进制CRC校验码
byte[] SendToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//
信息码+16进制CRC校验码+换行符
SendToClientString = SendToClientString + HexCrcCode(SendToClientBytes, 8) + Convert.ToChar(0x0D);
//
将字符串转换成字节数组
byte[] SendingToClientBytes = System.Text.Encoding.Default.GetBytes(SendToClientString);
//
将字节数组发送到客户端的卡机
(sender as CardMachine).SavedSocketOfNewlyConnected.Send(SendingToClientBytes);
}
ListViewItem listViewItem = this.PassedRecordlistView.Items.Insert(0, EmpNo);
listViewItem.SubItems.AddRange(new string[] { EmpName, PassingTime, CardNo, PassingStateInfo, MachineNo, ReadHeadNo });
}
}
catch (System.Exception ex)
{
//MiddleListBox
中显示CardMachine_OnReceiveData方法出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: CardMachine_OnReceiveData方法中的错误 "
+ ex.ToString());
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
// PassedRecordlistView
中显示的数据超过500条,就删除索引为 1 的那条记录
if (this.PassedRecordlistView.Items.Count >= 500)
PassedRecordlistView.Items.RemoveAt(1);
}
///<summary>
///
通过MainForm_Load事件中创建的线程启动服务器端Socket监听
///</summary>
private void BeginServerSocketListening()
{
byte[] bytes = new byte[1024];
int i;
string ClientMachineIP;
try
{
//
读取服务器IP地址
IPAddress ServerIp = GetServerIP();
//
指定双方在8000端口上通讯,也可以把8000写到配置文件中
IPEndPoint iep = new IPEndPoint(ServerIp, 8000);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] byteMessage = new byte[100];
ServerSocket.Bind(iep);
ServerSocket.Listen(0);
//
“永真循环”,在FormClosing事件中重新设置IsServerSocketRunning
//
为False,以退出这个“死循环”,退出服务器Socket处于等待连接的状态
while (IsServerSocketRunning)
{
this.Text = "
卡机服务器IP[ "
+ iep.ToString() + " ]
正在监听客户端卡机的连线请求 ‥‥‥"
;
// Accept()
方法执行完毕,目的是等待客户端Socket对象的连接请求
//
当客户端Socket执行Send(byte[])方法时,该行代码才继续顺序向
//
下执行,否则就一直处于等待被连接的状态,代码执行暂停在该行;
//
返回值是为新建连接创建新的 Socket对象,它包含了本地终结点和
//
远程终结点,还包含了Connected属性是否已连接到远程主机(客户
//
端卡机)和Available 属性(已经从网络接收且可供读取的数据量)等等
//
方法和属性信息。
SocketOfNewlyConnection = ServerSocket.Accept();
//
新建一个卡机对象实例,将已创建的新 Socket 对象包装进来
CardMachine cardMachine = new CardMachine(SocketOfNewlyConnection);
//
实例化委托类型的事件OnReceiveData,当服务器Socket实例_ServerSocket[它是SocketOfNewlyConnection赋给的值]收到的字节
//
长度大于42个字节并且OnReceiveData事件非null值时,触发事件要执行的方法CardMachine_OnReceiveData()
cardMachine.OnReceiveData += new CardMachine.DegReceiveData(CardMachine_OnReceiveData);
//
获取远程终结点(客户端卡机的IP和端口)中的IP地址
ClientMachineIP = ((IPEndPoint)(SocketOfNewlyConnection.RemoteEndPoint)).Address.ToString();
//
遍历配置文件(app.config)中用户输入的卡机数目
for (i = 0; i < CardMachineList.Count; i++)
{
//
如果保存在卡机集合列表中存在与从远程终结点中获得的IP地址
if (CardMachineList[i].ClientMachineIpAddress == ClientMachineIP)
{ //
那么就用最新的卡机对象取代过去的卡机对象;
CardMachineList[i] = cardMachine;
//
并将连接状态的图片设置为“已连接上”的图片;
PictureBoxArray[i + 1].Image = ConnectedPictureBox.Image;
//
设置客户端卡机的编号
cardMachine.ClientMachineNo = i + 1;
}
}
//MiddleListBox
中显示一空行
MiddleListBox.Items.Add("");
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
//MiddleListBox
中显示数据来自那台卡机(IP地址和端口)的数据
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: 服务器已收到来自客户端[ "
+ SocketOfNewlyConnection.RemoteEndPoint.ToString() + " ]
发过来的数据"
);
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
catch (System.Exception ex)
{
//MiddleListBox
中显示BeginServerSocketListening方法中出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: BeginServerSocketListening方法中的错误 "
+ ex.ToString());
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
private void MainForm_Load(object sender, EventArgs e)
{
int i, j;
//MiddleListBox
中显示服务器启动时间
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: 服务器已经启动 "
);
//
获得客户端卡机连接到服务状态下的“连接状态”图片
ConnectedPictureBox = new PictureBox();
ConnectedPictureBox.Image = this.imageList1.Images[1];
//
获得客户端卡机断开与服务连接的“断开状态”图片
DisconnectedPictureBox = new PictureBox();
DisconnectedPictureBox.Image = this.imageList1.Images[0];
//
读取配置文件(app.config)中用户输入的卡机数目
MachineCount = Convert.ToInt32(ConfigurationManager.AppSettings["MachineCount"]);
for (i = 0; i < MachineCount; i++)
{
//
新建一个卡机对象实例
CardMachine cardMachine = new CardMachine(null);
//
加 1 是因为卡机编号从1开始编号
j = i + 1;
//
卡机对象实例保存到卡机集合列表中
CardMachineList.Add(cardMachine);
//
读取配置文件(app.config)中用户输入的卡机编号对应的IP地址保存到卡机集合列表中
CardMachineList[i].ClientMachineIpAddress = ConfigurationManager.AppSettings["MachineNo" + j.ToString()];
//
读取配置文件(app.config)中用户输入的卡机编号保存到卡机集合列表中
CardMachineList[i].ClientMachineNo = j;
}
//
根据卡机数目初始化客户端卡机处于“断开状态”图片和卡机编号
InitMachineImage(MachineCount);
try
{
//
创建一个线程用来准备启动服务端的Socket监听
ThreadOfStartServerSocketListening = new Thread(new ThreadStart(BeginServerSocketListening));
//
正式启动服务端的Socket监听
ThreadOfStartServerSocketListening.Start();
}
catch (Exception ex)
{
//MiddleListBox
中显示MainForm_Load事件中的错误
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: MainForm_Load事件中的错误 "
+ ex.ToString());
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
//
结束“永真循环”退出服务器Socket处于等待连接的状态
IsServerSocketRunning = false;
for (int i = 0; i < this.CardMachineList.Count; i++)
{
this.CardMachineList[i].Close();
}
}
private void timer1_Tick(object sender, System.EventArgs e)
{
try
{
ServerPromgramRunningSeconds++;
//
每隔60秒报告一次每台卡机的连接状态
if (ServerPromgramRunningSeconds % 60 == 0)
{
//
重新记时,避免数据过大占用内存
ServerPromgramRunningSeconds = 0;
//TopListBox
中显示一空行
TopListBox.Items.Add("");
//TopListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (TopListBox.Items.Count > 2000) { TopListBox.Items.RemoveAt(1); }
for (int i = 0; i < CardMachineList.Count; i++)
{
//TopListBox
中显示卡机IP和连接状态
TopListBox.Items.Add(DateTime.Now.ToString() + "
: [ "
+ CardMachineList[i].ClientMachineNo.ToString() +
" ]
号机IP[ "
+ CardMachineList[i].ClientMachineIpAddress +
" ]
连接状态[ "
+ CardMachineList[i].ClientIsConnected.ToString() + " ]");
//TopListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (TopListBox.Items.Count > 2000) { TopListBox.Items.RemoveAt(1); }
}
//MiddleListBox
中显示一空行
MiddleListBox.Items.Add("");
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
//BottomListBox
中显示一空行
BottomListBox.Items.Add("");
//BottomListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
}
for (int i = 0; i < CardMachineList.Count; i++)
{
//
每台卡机每隔1秒钟ClientConnectedLifeTime会自动加上1秒(Timer事件每隔1秒触发一次)
CardMachineList[i].ClientConnectedLifeTime += 1;
//
如果某一台卡机连接时间超过70秒时
if (CardMachineList[i].ClientConnectedLifeTime > 70)
{
//(1)
将该台卡机连接时间清0
CardMachineList[i].ClientConnectedLifeTime = 0;
//(2)
如果该台卡机还处在“已连接上”上的状态
if (CardMachineList[i].ClientIsConnected == true)
{
//(a)
将该卡机已连接状态的图片设置为断开状态的图片
PictureBoxArray[CardMachineList[i].ClientMachineNo].Image = DisconnectedPictureBox.Image;
//(b)
如果该卡机已与服务器通讯了
if (CardMachineList[i].SavedSocketOfNewlyConnected != null)
{
//(i)
设置ServerSocketIsActive为非活动状态;
//(ii)
禁用SavedSocketOfNewlyConnected上的发送和接收并释放所有关联的资源;
//(iii)
结束ThreadOfServerIsWaitingForClientData线程的执行。
CardMachineList[i].Close();
}
//(c)
将该卡机的连接属性设置为断开连接
CardMachineList[i].ClientIsConnected = false;
//(d)
将该卡机设置为非活动状态.
CardMachineList[i].ServerSocketIsActive = false;
}
//BottomListBox
中显示一空行
BottomListBox.Items.Add("");
//BottomListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
for (int j = 0; j < CardMachineList.Count; j++)
{
//(4)
报告每台卡机的连接状态
BottomListBox.Items.Add(DateTime.Now.ToString() + "
: [ "
+ CardMachineList[j].ClientMachineNo.ToString() +
" ]
号机IP[ "
+ CardMachineList[j].ClientMachineIpAddress +
" ]
连接状态[ "
+ CardMachineList[j].ClientIsConnected.ToString()+" ]");
//BottomListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (BottomListBox.Items.Count > 2000) { BottomListBox.Items.RemoveAt(1); }
}
}
}
}
catch (System.Exception ex)
{
//MiddleListBox
中显示timer1_Tick 事件中出现错误的时间
MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: timer1_Tick 事件中的错误 "
+ ex.ToString());
//MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MiddleListBox.Items.Count > 2000) { MiddleListBox.Items.RemoveAt(1); }
}
}
}
}
2.MainForm.Designer.cs:
namespace
Server
{
partial class MainForm
{
///<summary>
/// Required designer variable.
///</summary>
private System.ComponentModel.IContainer components = null;
///<summary>
/// Clean up any resources being used.
///</summary>
///<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
try
{
ServerSocket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
ServerSocket.Close();
ThreadOfStartServerSocketListening.Abort();
}
catch { }
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
Windows Form Designer generated code
///<summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///</summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.PassedRecordlistView = new System.Windows.Forms.ListView();
this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
this.columnHeader3 = new System.Windows.Forms.ColumnHeader();
this.columnHeader4 = new System.Windows.Forms.ColumnHeader();
this.columnHeader5 = new System.Windows.Forms.ColumnHeader();
this.columnHeader6 = new System.Windows.Forms.ColumnHeader();
this.columnHeader7 = new System.Windows.Forms.ColumnHeader();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.ListViewImageConnectingStatus = new System.Windows.Forms.ListView();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.SuspendLayout();
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 55);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(762, 530);
this.tabControl1.TabIndex = 0;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.PassedRecordlistView);
this.tabPage1.Location = new System.Drawing.Point(4, 21);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(754, 505);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "
通行记录"
;
this.tabPage1.UseVisualStyleBackColor = true;
//
// PassedRecordlistView
//
this.PassedRecordlistView.AllowColumnReorder = true;
this.PassedRecordlistView.BackColor = System.Drawing.Color.Black;
this.PassedRecordlistView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3,
this.columnHeader4,
this.columnHeader5,
this.columnHeader6,
this.columnHeader7});
this.PassedRecordlistView.Dock = System.Windows.Forms.DockStyle.Fill;
this.PassedRecordlistView.Font = new System.Drawing.Font("PMingLiU", 9F);
this.PassedRecordlistView.ForeColor = System.Drawing.Color.Lime;
this.PassedRecordlistView.FullRowSelect = true;
this.PassedRecordlistView.Location = new System.Drawing.Point(3, 3);
this.PassedRecordlistView.Name = "PassedRecordlistView";
this.PassedRecordlistView.Size = new System.Drawing.Size(748, 499);
this.PassedRecordlistView.TabIndex = 0;
this.PassedRecordlistView.UseCompatibleStateImageBehavior = false;
this.PassedRecordlistView.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text = "
工号"
;
this.columnHeader1.Width = 80;
//
// columnHeader2
//
this.columnHeader2.Text = "
姓名"
;
this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader2.Width = 80;
//
// columnHeader3
//
this.columnHeader3.Text = "
时间"
;
this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader3.Width = 133;
//
// columnHeader4
//
this.columnHeader4.Text = "
卡号"
;
this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader4.Width = 91;
//
// columnHeader5
//
this.columnHeader5.Text = "
状态"
;
this.columnHeader5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.columnHeader5.Width = 127;
//
// columnHeader6
//
this.columnHeader6.Text = "
机器号"
;
this.columnHeader6.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// columnHeader7
//
this.columnHeader7.Text = "
进出"
;
this.columnHeader7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// tabPage2
//
this.tabPage2.Location = new System.Drawing.Point(4, 21);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(754, 505);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "
终端设备运行信息"
;
this.tabPage2.UseVisualStyleBackColor = true;
//
// ListViewImageConnectingStatus
//
this.ListViewImageConnectingStatus.BackColor = System.Drawing.SystemColors.Control;
this.ListViewImageConnectingStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ListViewImageConnectingStatus.Location = new System.Drawing.Point(0, 0);
this.ListViewImageConnectingStatus.Name = "ListViewImageConnectingStatus";
this.ListViewImageConnectingStatus.Size = new System.Drawing.Size(762, 55);
this.ListViewImageConnectingStatus.TabIndex = 1;
this.ListViewImageConnectingStatus.UseCompatibleStateImageBehavior = false;
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// imageList1
//
this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream")));
this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
this.imageList1.Images.SetKeyName(0, "");
this.imageList1.Images.SetKeyName(1, "");
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(762, 585);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.ListViewImageConnectingStatus);
this.Name = "MainForm";
this.Text = "
智能通道系统"
;
this.Load += new System.EventHandler(this.MainForm_Load);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.ListView PassedRecordlistView;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.ListView ListViewImageConnectingStatus;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.ImageList imageList1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.ColumnHeader columnHeader5;
private System.Windows.Forms.ColumnHeader columnHeader6;
private System.Windows.Forms.ColumnHeader columnHeader7;
}
}
3.CardMachineCollection.cs:
//***********************************************************************************************
//
作者 :郑紫至
//
创建日期:2008-03-14
//
邮件地址:zhengzizhi@mail.china.com
//
博客地址:http://hi.csdn.net/zhengzizhi
//
备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//***********************************************************************************************
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Collections;
namespace
Server
{
public class CardMachineCollection : CollectionBase
{
public CardMachine this[int index]
{
get { return ((CardMachine)List[index]); }
set { List[index] = value; }
}
public int Add(CardMachine value)
{
return (List.Add(value));
}
public void Remove(CardMachine value)
{
List.Remove(value);
}
}
}
4.CardMachine.cs
:
//******************************************************************************************
//
作者 :郑紫至
//
创建日期:2008-03-14
//
邮件地址:zhengzizhi@mail.china.com
//
博客地址:http://hi.csdn.net/zhengzizhi
//
备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//******************************************************************************************
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Net;
using
System.Net.Sockets;
using
System.Data.SqlClient;
using
System.Threading;
using
System.Configuration;
using
System.Data;
namespace
Server
{
public class CardMachine
{
///<summary>
///
保存由服务器Accecpt方法返回的一个新创建的Socket对象
///</summary>
public Socket SavedSocketOfNewlyConnected=null;
public Thread ThreadOfServerIsWaitingForClientData;
public SqlConnection SqlConn=null;
public SqlCommand SqlComm=null;
///<summary>
/// ServerSocketIsActive
默认为活动状态
///</summary>
public bool ServerSocketIsActive = true;
///<summary>
///
委托类型的事件
///</summary>
public event DegReceiveData OnReceiveData;
public delegate void DegReceiveData(object sender, string ReceiveString, int ReceiveStringLength, byte[] ReceiveBytes);
private int _ClientConnectedLifeTime = 0;
///<summary>
///
卡机连接服务器的秒数( 默认为0 )
///</summary>
public int ClientConnectedLifeTime
{
get { return _ClientConnectedLifeTime; }
set { _ClientConnectedLifeTime = value; }
}
private int _ClientMachineNo = 0;
///<summary>
///
卡机编号( 默认为0 )
///</summary>
public int ClientMachineNo
{
get { return _ClientMachineNo; }
set { _ClientMachineNo = value; }
}
private bool _ClientIsConnected = false;
///<summary>
///
卡机连接状态( 默认为断开 )
///</summary>
public bool ClientIsConnected
{
get { return _ClientIsConnected; }
set { _ClientIsConnected = value; }
}
private string _ClientMachineIpAddress = string.Empty;
///<summary>
///
卡机IP地址
///</summary>
public string ClientMachineIpAddress
{
get { return _ClientMachineIpAddress; }
set { _ClientMachineIpAddress = value; }
}
///<summary>
///
在已连接数据库的状态下,建立一个操作数据库存储过程的SqlCommand对象实例SqlComm,并定义存储过程中
///
要使用的参数类型和长度,最后线程启动ServerIsWaitingForClientData()方法接收来自客户端发过来的字节数据
///</summary>
///<param name="SocketOfNewlyConnected">
服务器Accecpt方法返回的新建Socket对象
</param>
public CardMachine(Socket SocketOfNewlyConnected)
{
if (SocketOfNewlyConnected != null)//
在执行窗体Load事件的时候会传null值过来,其它情况都是非null值
{
SqlConn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
SqlConn.Open();
SqlComm = new SqlCommand("dbo.[CheckDiningEmpInfoByCardNo]", SqlConn);
SqlComm.CommandType = System.Data.CommandType.StoredProcedure;
SqlComm.Connection = SqlConn;
SqlComm.Parameters.Add(new SqlParameter("@RETURN_VALUE", SqlDbType.Int, 4,
ParameterDirection.ReturnValue, false, (System.Byte)(0),
(System.Byte)(0), "",DataRowVersion.Current, null));
SqlComm.Parameters.Add(new SqlParameter("@CardNo", SqlDbType.VarChar, 10));
SqlComm.Parameters.Add(new SqlParameter("@MachineNo", SqlDbType.VarChar, 5));
SqlComm.Parameters.Add(new SqlParameter("@ReadHeadNo", SqlDbType.Int, 4));
SqlComm.Parameters.Add(new SqlParameter("@EmpNo", SqlDbType.VarChar, 8,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"", DataRowVersion.Current, null));
SqlComm.Parameters.Add(new SqlParameter("@EmpName", SqlDbType.NVarChar, 20,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"", DataRowVersion.Current, null));
SqlComm.Parameters.Add(new SqlParameter("@CardPassingState", SqlDbType.Int, 4,
ParameterDirection.Output, false, (System.Byte)(0),
(System.Byte)(0),"", DataRowVersion.Current, null));
//
设置卡机连接服务器的状态为“已连接上”.
ClientIsConnected = true;
//
获取远程终结点(客户端卡机的IP和端口)中的IP地址
ClientMachineIpAddress =((IPEndPoint)(SocketOfNewlyConnected.RemoteEndPoint)).Address.ToString();
//
保存服务器Accecpt方法返回的新建Socket对象到SavedSocketOfNewlyConnected变量中
SavedSocketOfNewlyConnected = SocketOfNewlyConnected;
//
创建一个新线程准备执行ServerIsWaitingForClientData()方法
ThreadOfServerIsWaitingForClientData = new Thread(new ThreadStart(ServerIsWaitingForClientData));
//
启动线程,开始执行ServerIsWaitingForClientData()方法
ThreadOfServerIsWaitingForClientData.Start();
}
}
///<summary>
///
///</summary>
public void ServerIsWaitingForClientData()
{
//
保存客户端发到服务器的字节数组
byte[] BytesOfClientToServer = new byte[1024];
int MachineNo, ServerReceivedFromClientLengthOfBytes = 0;
try
{
// SavedSocketOfNewlyConnected
会在MainForm的timer1_Tick事件中每隔70秒释放一次
while (ServerSocketIsActive && SavedSocketOfNewlyConnected != null)
{
//
使用SavedSocketOfNewlyConnected对象接收来自客户端Socket对象发过来的字节数据并
//
且将接收方法返回的字节长度数据保存到ServerReceivedFromClientLengthOfBytes变量中
ServerReceivedFromClientLengthOfBytes = SavedSocketOfNewlyConnected.Receive(BytesOfClientToServer);
//
定义一个将接收到的字节转换成字符串的变量
string ServerReceivedFromClientString = string.Empty ;
//
将字节转换成字符串
ServerReceivedFromClientString += Encoding.ASCII.GetString(
BytesOfClientToServer, 0, ServerReceivedFromClientLengthOfBytes);
//
if (ServerReceivedFromClientString.Length == 11)
{
//
从第0位到第10位(长度为11)这段字符串中截取第1位和第2位表示卡机编号的字串
MachineNo = Convert.ToInt32(ServerReceivedFromClientString.Substring(1, 2));
// MiddleListBox
中显示一空行
MainForm.MiddleListBox.Items.Add("");
// MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) { MainForm.MiddleListBox.Items.RemoveAt(1); };
// MiddleListBox
中显示当前卡机完成一次完整的通讯结束信号
MainForm.MiddleListBox.Items.Add(DateTime.Now.ToString() + "
: 服务器已收到[ "
+
MachineNo.ToString() + " ]
号卡机传回本次完整通讯结束的<EOF>信号"
);
// MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) { MainForm.MiddleListBox.Items.RemoveAt(1); };
//
将当前卡机编号的连接状态图片设置为“已连接上”的图片;
MainForm.PictureBoxArray[MachineNo].Image = MainForm.ConnectedPictureBox.Image;
ClientConnectedLifeTime = 0;
}
if (ServerReceivedFromClientString.IndexOf("<EOF>") > -1)
{
break;//
如果接收的字符串包含了“<EOF>”标记,退出以结束本次通讯
}
//
接收字节长度大于 42 表示一次完整通讯客户端发过来真正有用的数据
if ((ServerReceivedFromClientLengthOfBytes > 42) && (OnReceiveData != null))
//
{ OnReceiveData(this, ServerReceivedFromClientString, ServerReceivedFromClientLengthOfBytes, BytesOfClientToServer); }
}
}
catch (Exception ex)
{
// MiddleListBox
中显示ServerIsWaitingForClientData方法出现错误的时间
MainForm.MiddleListBox.Items.Add(DateTime.Now.ToString() +
"
: ServerIsWaitingForClientData方法中的错误 "
+ ex.ToString());
// MiddleListBox
中显示的数据超过2000条,就删除索引为 1 的那条记录
if (MainForm.MiddleListBox.Items.Count > 2000) { MainForm.MiddleListBox.Items.RemoveAt(1); };
}
}
///<summary>
///
设置ServerSocketIsActive为非活动状态;
///
禁用SavedSocketOfNewlyConnected上的发送和接收并释放所有关联的资源;
///
结束ThreadOfServerIsWaitingForClientData线程的执行。
///</summary>
public void Close()
{
ServerSocketIsActive = false;
try
{
if (SavedSocketOfNewlyConnected != null)
{
//(i)
禁用SavedSocketOfNewlyConnected上的发送和接收
SavedSocketOfNewlyConnected.Shutdown(SocketShutdown.Both);
//(ii)
关闭 SavedSocketOfNewlyConnected连接并释放所有关联的资源
SavedSocketOfNewlyConnected.Close();
//(iii)
结束用来启动ServerIsWaitingForClientData()方法的线程
ThreadOfServerIsWaitingForClientData.Abort();
}
}
catch
{ }
}
}
}
5. app.config
:
<?
xml
version
=
"1.0"encoding="utf-8" ?>
<
configuration
>
<
configSections
>
</
configSections
>
<
connectionStrings
>
<
add
name
=
"Server.Properties.Settings.IRSConnectionString"
connectionString
=
""
providerName
=
"System.Data.SqlClient" />
</
connectionStrings
>
<
appSettings
>
<
add
key
=
"ConnectionString"value="Data Source=VSNET2008/SQLEXPRESS;Initial Catalog=IRS;Integrated Security=True"/>
<
add
key
=
"MachineCount"value="9"/>
<
add
key
=
"MachineNo1"value="192.168.1.91"/>
<
add
key
=
"MachineNo2"value="192.168.1.92"/>
<
add
key
=
"MachineNo3"value="192.168.1.93"/>
<
add
key
=
"MachineNo4"value="192.168.1.94"/>
<
add
key
=
"MachineNo5"value="192.168.1.95"/>
<
add
key
=
"MachineNo6"value="192.168.1.96"/>
<
add
key
=
"MachineNo7"value="192.168.1.97"/>
<
add
key
=
"MachineNo8"value="192.168.1.98"/>
<
add
key
=
"MachineNo9"value="192.168.1.99"/>
</
appSettings
>
</
configuration
>
6. Program
:
//***********************************************************************************************
//
作者 :郑紫至
//
创建日期:2008-03-14
//
邮件地址:zhengzizhi@mail.china.com
//
博客地址:http://hi.csdn.net/zhengzizhi
//
备注说明:欢迎大家转载我的博客内容,代码版权归本人所有,请保留此信息。
//***********************************************************************************************
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Windows.Forms;
namespace
Server
{
static class Program
{
///<summary>
/// The main entry point for the application.
///</summary>
[STAThread]
static void Main()
{
Control.CheckForIllegalCrossThreadCalls = false;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
Server
项目所有代码全部发布完毕(包括自动生成的代码)
在整个方案中的结构如下图所显: