我正在编写一个程序,它将存在于超级PC"在我的工作实验室。它的工作是不断查询我们的客户数据库,主动寻找我们遇到的常见错误。
它通过使用可调整的计时器并简单地运行查询和数据库列表并解释结果来实现这一点。(使用配置UI添加查询和数据库连接)
此程序与我编写的另一个应用程序的TCP客户端/服务器连接存在于我的团队成员个人计算机上。消息从服务器(查询)程序发送到客户端程序,警告我的团队在数据库中发现错误。
我遇到的问题偶尔是在建立数据库连接或运行查询的同时通过套接字发送消息,这会导致服务器程序崩溃而无需解释。
运行查询的方法总是在自己的线程中调用,服务器连接也在自己的线程中进行。
此外,我已将所有数据库方法和客户端服务器方法放置在Try / Catch块中,这些块被设置为捕获所有异常并显示堆栈跟踪,但由于某些原因,当它崩溃时不会遇到任何捕获。
runQueries方法是从C#.Net System.Timers.Timer调用的,它应该在每个tick上启动一个新线程。
以下是我的客户端/服务器方法和查询方法
private void serverMeth()
{
try
{
/*conbox.Text = conbox.Text + "The server is running at port 8001..." + Environment.NewLine;
conbox.Text = conbox.Text + "The local End point is :" + myList.LocalEndpoint + Environment.NewLine;
conbox.Text = conbox.Text + "Waiting for a connection....." + Environment.NewLine;*/
msglist.Add("The server is running at port 8001...");
msglist.Add("The local end point is: " + myList.LocalEndpoint);
msglist.Add("Waiting for a connection...");
writeToLog("Listening for connection at "+myList.LocalEndpoint);
/* Start Listeneting at the specified port */
while (true)
{
gatherErrors();
myList.Start();
//Socket s = myList.AcceptSocket();
s = myList.AcceptSocket();
//conbox.Text = conbox.Text + "Connection accepted from " + s.RemoteEndPoint + Environment.NewLine;
msglist.Add("Connection accepted from " + s.RemoteEndPoint);
writeToLog("Connection Established @" + myList.LocalEndpoint);
byte[] b = new byte[20000];
int k = s.Receive(b);
//conbox.Text = conbox.Text + "Recieved..." + Environment.NewLine;
msglist.Add("Recieved...");
writeToLog("Message Recieved from Command Center");
//for (int i = 0; i < k; i++)
//{ conbox.Text = conbox.Text + Convert.ToChar(b[i]); }
string message = ""; //allows it to store the entire message in one line
string dt = DateTime.Now.ToString("MM-dd-yyyy hh:mm:ss");
string eid = "TEST ID";
for (int i = 0; i < k; i++)
{ message = message + Convert.ToChar(b[i]); }
if (message.Contains(uniquekey))
{
writeToLog("Message contains correct passcode");
message = message.Replace(uniquekey, "");
String[] splits = message.Split(',');
message = message.Replace("," + splits[1], "");
writeToLog("Connection from " + splits[1]);
msglist.Add(message); //this takes the completed message and adds it.
//DO IGNORE STUF HERE
if (!message.Equals(""))
{
//Message contains error key
Error erro = null;
for (int i = 0; i < errorss.Count; i++)
{
if (errorss[i].getKey().Equals(message)) {
erro = errorss[i];
}
}
Stage st = null;
if (erro != null)
{
for (int i = 0; i < stages.Count; i++)
{
if (stages[i].errContainCheck(erro))
{
st = stages[i];
}
}
}
if (st != null)
{
st.addIgnore(erro);
writeToLog("Error: " + erro.getKey() + "ignored");
}
}
//conbox.Text = conbox.Text + Environment.NewLine;
msglist.Add(" ");
string msg = "";
string log = "Error(s): ";
for (int i = 0; i < errorss.Count; i++)
{
msg += errorss[i].getTime() + "|"+errorss[i].getMsg()+"|" + errorss[i].getSite()+"|"+errorss[i].getKey();
msg += ",";
log += errorss[i].getKey()+",";
}
log+= "sent to Command Center";
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes(msg));
//conbox.Text = conbox.Text + "\nSent Acknowledgement" + Environment.NewLine;
msglist.Add("\nSent Acknowledgement");
writeToLog(log);
}
else
{
message = "Unauthorized access detected. Disregarding message.";
//.Add(message); //this takes the completed message and adds it.
//conbox.Text = conbox.Text + Environment.NewLine;
msglist.Add(" ");
writeToLog("Passcode mismatch");
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("Access Denied. Unique key mismatch."));
//conbox.Text = conbox.Text + "\nSent Acknowledgement" + Environment.NewLine;
msglist.Add("\nSent Denial Acknowledgement");
}
/* clean up */
s.Close();
myList.Stop();
if (quit == true)
{
break;
}
}
}
catch (Exception err)
{
//conbox.Text = conbox.Text + "Error..... " + err.StackTrace + Environment.NewLine;
msglist.Add("Error..... " + err.StackTrace);
writeToLog("ERROR: "+err.StackTrace);
}
}
private void sasDownload()
{
int selItemList;
selItemList = saerrlist.SelectedIndex;
saerrlist.Items.Clear(); //clears the list before redownload
saerrgrid.Rows.Clear();
try
{
TcpClient tcpclnt = new TcpClient();
//clibox.Text = clibox.Text + "Connecting....." + Environment.NewLine;
tcpclnt.Connect(staralertip.Text, 8001);
// use the ipaddress as in the server program
//clibox.Text = clibox.Text + "Connected" + Environment.NewLine;
//clibox.Text = clibox.Text + "Enter the string to be transmitted : " + Environment.NewLine;
String str = "982jsdf293jsadd02jkdas20dka2";
Stream stm = tcpclnt.GetStream();
if (ackClick)
{
str += ackKey;
ackClick = false;
}
String name = "User not found";
for (int i = 0; i < users.Count(); i++)
{
if(users[i].sys_id.Equals(SNLists.loggedinuser)){
name = users[i].name;
break;
}
}
str += "," + name;
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
//clibox.Text = clibox.Text + "Transmitting....." + Environment.NewLine;
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[20000];
int k = stm.Read(bb, 0, 20000);
string incmsg = "";
for (int i = 0; i < k; i++)
incmsg = incmsg + Convert.ToChar(bb[i]);
string tempmsg = "";
foreach (char c in incmsg)
{
if (c != ',')
{
tempmsg = tempmsg + c;
}
else if (c == ',')
{
saerrlist.Items.Add(tempmsg);
saerrgrid.Rows.Add(tempmsg.Split('|')[0], tempmsg.Split('|')[1], tempmsg.Split('|')[2], tempmsg.Split('|')[3]);
tempmsg = "";
}
}
saerrlist.Items.Add(tempmsg);
//saerrgrid.Rows.Add(tempmsg.Split('|')[0], tempmsg.Split('|')[1], tempmsg.Split('|')[2]);
//MessageBox.Show(incmsg);
tcpclnt.Close();
}
catch (Exception err)
{
//MessageBox.Show("Error..... " + err.StackTrace, "STAR Command Center: Connectivity Error");
staralertTimer.Enabled = false;
MessageBox.Show("Error downloading recent errors from STAR Alert System.\n\nPlease confirm STAR Alert is running " +
"and hit \"Refresh\" in the STAR Alert tab." + "\n" + err, "STAR Command Center: Connectivity Error");
}
saerrlist.SelectedIndex = selItemList;
}
public void runQueries()
{
OracleConnection con = new OracleConnection();
int siteNum = -1;
try
{
writeToLog("Call to runQueries");
List<List<Error>> results = new List<List<Error>>();
for (int i = 0; i < ppreset.getSites().Count(); i++)
{
siteNum = i;
Site s = ppreset.getSites()[i];
if (s.getStatus().Equals("ACTIVE"))
{
//OracleConnection con = new OracleConnection();
String it = "User Id=" + s.getLogin() + ";Password=" + s.getPassword() + ";Data Source=" + s.getDbName();
con.ConnectionString = it;
//con.OpenAsync();
con.Open();
writeToLog("Connection opened for site: " + s.getSite());
List<Error> subResults = new List<Error>();
for (int j = 0; j < s.getQueries().Count(); j++)
{
Query q = s.getQueries()[j];
string sql = q.getCode();
List<string> columns = getColumns(sql);
List<List<String>> mast = new List<List<String>>();
for (int m = 0; m < columns.Count(); m++)
{
mast.Add(new List<String>());
}
OracleCommand cmd = new OracleCommand(sql, con);
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
writeToLog("Execute SQL, Begin Reading results...");
// dr.Read();
//List<String> results = new List<String>();
if (dr.HasRows)
{
//MessageBox.Show("has rows");
while (dr.Read())
{
//string result = "";
for (int p = 0; p < columns.Count(); p++)
{
if (columns.Count() != 0)
{
mast[p].Add(dr[columns[p]].ToString());
}
}
//results.Add(result);
}
}
subResults.AddRange(ruleCheck(mast, q.getRules(), s.getQueries()[j], ppreset.getSites()[i].getSite()));
cmd.Dispose();
writeToLog("Done reading");
}
results.Add(subResults);
// con.Dispose();
con.Close();
writeToLog("Connection Closed for site: " + s.getSite());
}
}
//we now have all of the error strings gathered from running all queries on all sites in the given preset
//lets send them to a method that will change the status' of the modules and makem RAVVEEEEE
//update(results);
if (errors == null && results.Count != 0)
{
//MessageBox.Show("errors = results");
errors = results;
writeToLog("First error found...errors = results");
for (int i = 0; i < results.Count; i++)
{
for (int j = 0; j < results[i].Count; j++)
{
if (foncig.lallerdisc == true)
{
sendLyncMsg(results[i][j].getMsg());
writeToLog("Lync Msg sent");
}
}
}
}
else
{
for (int i = 0; i < results.Count; i++)
{
for (int j = 0; j < results[i].Count; j++)
{
errors[i].Add(results[i][j]);
writeToLog("Error: " + results[i][j].getKey() + " added");
// MessageBox.Show("Error added to errors");
//////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//LYNC STUFF CAN GO HERE///////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////FOR EACH ERROR ADDED TO MASTER LIST SEND LYNC///////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (foncig.lallerdisc == true)
{
sendLyncMsg(results[i][j].getMsg());
writeToLog("Lync msg sent");
}
}
}
}
}
catch (Exception e)
{//MessageBox.Show("Err: " + e);
badConn[siteNum] += "x";
writeToLog("Connection error strike added to " + ppreset.getSites()[siteNum].getSite());
con.Close();
checkForBadConn();
writeToLog( e.StackTrace);
}
//foncig.errors = errors;
//here we will check all of the errors in results against all of the errors in errors
//if the error is not in errors add it
//errors = results;
}
查询计时器初始化
queryTimer = new System.Timers.Timer(120000);
queryTimer.Elapsed += queryTimer_Tick;
queryTimer.Enabled = true;
查询计时器的勾选方法
private void queryTimer_Tick(object sender, EventArgs e)
{
GC.Collect();
try
{
runQueries();
}
catch (OracleException err)
{
// MessageBox.Show("Err: " + err);
}
}
如何启动服务器线程
server = new Thread(serverMeth);
server.Start();
有谁知道为什么会这样?这两个程序都按照描述工作,并且当越来越多的客户端开始连接到服务器时,它们应该做它们应该做的事情,它变得越来越可能同时发生TCP连接和数据库连接。
2014年9月15日12:20更新
所以我试图从上次崩溃中上传一张日志照片...但我没有足够的重复点...无论如何,derp
这次日志中的最后一行来自日志清除(删除超过24小时的日志条目)
但是,当我将客户端程序设置为自动刷新时,程序才会崩溃。 IE客户端应用程序有一个按钮来请求来自服务器的消息,或者用户可以选择自动刷新,它将请求功能设置为计时器。
我唯一的另一个想法是多个线程同时尝试写入日志文件,但是我对log方法的写入使用了writeLinesAsync(),这样就不会有问题吗?
答案 0 :(得分:0)
此问题原因是多个线程同时尝试写入日志文件。
我通过遵循@ user469104的建议并创建一个内部锁定对象来锁定writeToLog方法来解决它。
客户端和服务器应用程序已经运行了好几天而不会中断。
谢谢大家!