同时使用Oracle连接和TCP客户端/服务器连接
本文关键字:连接 TCP 客户端 服务器 Oracle | 更新日期: 2023-09-27 18:22:05
我正在写一个程序,该程序将在我实验室的"超级PC"上运行。它的工作是不断主动地查询我们的客户数据库,寻找我们遇到的常见错误。
它通过使用一个可调整的定时器,简单地运行查询和数据库列表并解释结果来实现这一点。(使用配置UI添加查询和数据库连接)
这个程序与我编写的另一个应用程序有TCP客户端/服务器连接,该应用程序位于我的团队成员的个人计算机上。消息从服务器(查询)程序发送到客户端程序,提醒我的团队在数据库中发现错误。
我一直遇到的问题是,偶尔会在建立数据库连接或运行查询的同时,通过套接字发送一条消息,这会导致服务器程序崩溃,而没有任何解释。
运行查询的方法总是在其自己的线程中调用,服务器连接也是在其自己线程中进行的。
此外,我将所有DB方法和Client-Server方法都放在Try/Catch块中,这些块被设置为捕获所有异常并显示堆栈跟踪,但由于某种原因,当它崩溃时,它没有命中任何Catch。
runQueries方法是从一个C#.Net System.Timers.Timer调用的,它应该在每个刻度上启动一个新线程。
以下是我的客户端/服务器方法和查询方法
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连接和DB连接同时发生的可能性越来越大。
更新时间:2014年9月15日12:20
所以我试图上传一张上次崩溃日志的照片。。。但我没有足够的代表点。。。derp,无论如何
这一次,日志中的最后一行来自日志清除(删除超过24小时的日志条目)
然而,只有当我将客户端程序设置为自动刷新时,该程序才会崩溃。IE客户端应用程序有一个按钮,可以从服务器请求消息,或者用户可以选择自动刷新,将请求功能设置为计时器。
我唯一的另一个想法是多个线程试图同时写入日志文件,但是我的写入日志方法使用了writeLinesAsync(),所以这应该不是问题吗?
这个问题是由多个线程试图同时写入日志文件引起的。
我按照@user469104的建议解决了这个问题,并创建了一个内部锁定对象来锁定writeToLog方法。
客户端和服务器应用程序已经运行了好几天,没有中断。
谢谢大家!