我正在构建GPS应用程序,其中GPS设备通过tcp端口发送位置 我正在构建服务来阅读这些消息并将其保存到数据库
static void Main(string[] args)
{
TcpListener serverSocket = new TcpListener(8889);
TcpClient clientSocket = default(TcpClient);
int counter = 0;
serverSocket.Start();
// Console.WriteLine(" >> " + "Server Started");
counter = 0;
while (true)
{
counter += 1;
clientSocket = serverSocket.AcceptTcpClient();
// Console.WriteLine(" >> " + "Client No:" + Convert.ToString(counter) + " started!");
handleClinet client = new handleClinet();
client.startClient(clientSocket, Convert.ToString(counter));
}
clientSocket.Close();
serverSocket.Stop();
// Console.WriteLine(" >> " + "exit");
Console.ReadLine();
}
}
//Class to handle each client request separatly
public class handleClinet
{
static void WriteLog(string message, EventLogEntryType type)
{
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Application";
eventLog.WriteEntry(message, type, 101, 1);
}
}
static int InsideDangerArea(double Lat, double Lng)
{
string point = "POINT(" + Lng + " " + Lat + ")";
string ConnStr = "Data Source =.; Initial Catalog = GPS_Tracking;Integrated Security = True";
using (SqlConnection conn = new SqlConnection(ConnStr))
{
conn.Open();
using (SqlCommand comm = new SqlCommand("Select id from T_Geofncies", conn))
{
DataTable dt = new DataTable();
dt.Load(comm.ExecuteReader());
foreach (DataRow dr in dt.Rows)
{
string Query = " DECLARE @g geometry; DECLARE @h geometry; SET @g = (select(points) from T_Geofncies where id=" + dr["id"].ToString() + " );";
Query += " SET @h = geometry::STGeomFromText('" + point + "', 4326); SELECT @g.STContains(@h);";
comm.CommandText = Query;
int Val = Convert.ToInt32(comm.ExecuteScalar());
if (Val == 1)
{
conn.Close();
conn.Dispose();
return Convert.ToInt32(dr["id"]);
}
}
}
conn.Close();
conn.Dispose();
}
return 0;
}
static int OutsideSafeArea(double Lat, double Lng)
{
string point = "POINT(" + Lng + " " + Lat + ")";
string ConnStr = "Data Source =.; Initial Catalog = GPS_Tracking;Integrated Security = True";
using (SqlConnection conn = new SqlConnection(ConnStr))
{
conn.Open();
using (SqlCommand comm = new SqlCommand("Select id from T_SafeArea", conn))
{
DataTable dt = new DataTable();
dt.Load(comm.ExecuteReader());
foreach (DataRow dr in dt.Rows)
{
string Query = " DECLARE @g geometry; DECLARE @h geometry; SET @g = (select(points) from T_SafeArea where id=" + dr["id"].ToString() + " );";
Query += " SET @h = geometry::STGeomFromText('" + point + "', 4326); SELECT @g.STContains(@h);";
comm.CommandText = Query;
int Val = Convert.ToInt32(comm.ExecuteScalar());
if (Val == 1)
{
conn.Close();
conn.Dispose();
return Convert.ToInt32(dr["id"]);
}
}
}
conn.Close();
conn.Dispose();
}
return 0;
}
static SqlGeography GetGeographyFromText(String pText)
{
SqlString ss = new SqlString(pText);
SqlChars sc = new SqlChars(ss);
try
{
return SqlGeography.STPointFromText(sc, 4326);
}
catch (Exception ex)
{
throw ex;
}
}
TcpClient clientSocket;
string clNo;
public void startClient(TcpClient inClientSocket, string clineNo)
{
this.clientSocket = inClientSocket;
this.clNo = clineNo;
Thread ctThread = new Thread(doChat);
ctThread.Start();
}
private void doChat()
{
string ConnStr = "Data Source =.; Initial Catalog = GPS_Tracking;Integrated Security = True";
int requestCount = 0;
// byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
int i;
int size = (int)clientSocket.ReceiveBufferSize;
// Loop to receive all the data sent by the client.
Byte[] bytes = new Byte[size];
string data = "";
string IMEI;
while ((i = networkStream.Read(bytes, 0, bytes.Length)) != 0)
{
try
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
string[] tokens = data.Split(new[] { "GPRMC" }, StringSplitOptions.None);
var longest = Regex.Matches(data, @"\d+").Cast<Match>().OrderByDescending(m => m.Length).First();
IMEI = longest.ToString();
if (IMEI.Length > 15)
IMEI = IMEI.Substring(1);
foreach (string item in tokens)
{
try
{
string[] Values = item.Split(','); // Console.WriteLine("Received: {0}", data);
string time = Values[1];
// Console.WriteLine("Time= " + time);
string lat;
string lng;
string speed;
string date;
lat = Values[3];
lng = Values[5];
speed = Values[7];
date = Values[9];
string NewDString = date.Substring(2, 2) + date.Substring(0, 2) + date.Substring(4, 2);
// Console.WriteLine("IMEI= " + IMEI);
// Alternate choice: If the string has been input by an end user, you might
// want to format it according to the current culture:
// IFormatProvider culture = System.Threading.Thread.CurrentThread.CurrentCulture;
string myDate = (NewDString + time).Insert(2, "-").Insert(5, "-").Insert(8, " ").Insert(11, ":").Insert(14, ":");
double latDeg = Convert.ToDouble(Convert.ToDouble(lat).ToString().Substring(0, 2));
double latMin = Convert.ToDouble(Convert.ToDouble(lat).ToString().Substring(2));
double lngDeg = Convert.ToDouble(Convert.ToDouble(lng).ToString().Substring(0, 2));
double lngmin = Convert.ToDouble(Convert.ToDouble(lng).ToString().Substring(2));
double latmap = latDeg + (latMin / 60);
// OldLat=
double lngmap = lngDeg + (lngmin / 60);
//if ((Math.Round(latmap, 3) != Math.Round(OldLat, 3) && Math.Round(lngmap, 3) != Math.Round(OldLng, 3)) || idleRecord > 30)
//{
using (SqlConnection conn = new SqlConnection(ConnStr))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
// DbCommand also implements IDisposable
// create command with placeholders
cmd.CommandText =
"INSERT INTO T_Tracking " +
"([IMEI], [TrackTime], [Longitude], [Lattitude], [speed],[MapPoint],[SafeAreaID],[GeoFenceID]) " +
"VALUES(@IMEI, @TrackTime, @Longitude, @Lattitude, @speed,@MapPoint,@SafeAreaID,@GeoFenceID)";
SqlParameter p_IMEI = new SqlParameter("@IMEI", IMEI);
cmd.Parameters.Add(p_IMEI);
SqlParameter p_TrackTime = new SqlParameter("@TrackTime", myDate);
cmd.Parameters.Add(p_TrackTime);
SqlParameter p_Longitude = new SqlParameter("@Longitude", lngmap);
cmd.Parameters.Add(p_Longitude);
SqlParameter p_Lattitude = new SqlParameter("@Lattitude", latmap);
cmd.Parameters.Add(p_Lattitude);
SqlParameter p_Speed = new SqlParameter("@speed", speed);
cmd.Parameters.Add(p_Speed);
SqlParameter p_Points = new SqlParameter("@MapPoint", System.Data.SqlDbType.Udt);
p_Points.UdtTypeName = "geometry";
p_Points.Value = GetGeographyFromText("Point(" + lngmap + " " + latmap + ") ");
cmd.Parameters.Add(p_Points);
SqlParameter P_Safe = new SqlParameter("@SafeAreaID", OutsideSafeArea(latmap, lngmap));
cmd.Parameters.Add(P_Safe);
SqlParameter P_GeoFence = new SqlParameter("@GeoFenceID", InsideDangerArea(latmap, lngmap));
cmd.Parameters.Add(P_GeoFence);
// execute
cmd.ExecuteNonQuery();
}
//}
//else
// idleRecord = idleRecord + 1;
}
}
catch (Exception exp) { WriteLog(exp.ToString(), EventLogEntryType.Error); }
}
}
catch { }
}
}
catch (Exception ex)
{
// Console.WriteLine(" >> " + ex.ToString());
}
}
}
}
}
它工作正常,但问题是性能 它是具有5个设备的测试系统 它在10分钟内在服务器上消耗95%的内存 可以做些什么来优化代码
谢谢
答案 0 :(得分:0)
这里的问题是,每次进入新的套接字连接时,您都会创建一个即使在关闭底层连接时也永远不会结束的新线程。线程过程用MyApp.2016-10-01_1 // (100mb limit reached)
MyApp.2016-10-01_2
MyApp.2016-10-02
MyApp.2016-10-03_1 // (100mb limit reached)
MyApp.2016-10-03_2 // (100mb limit reached)
MyApp.2016-10-03_3
...
MyApp.2016-10-14
循环中的catch-all异常处理程序包装,因此当套接字连接关闭并抛出SocketException时,会捕获并忽略它,并且线程过程再次循环。这也将防止套接字对象的垃圾收集,并且可能也是高度CPU密集的。此外,main的末尾的清理代码将永远不会被调用,因为while(true)存在,并且实际上只会关闭最后一个客户端连接。
您的线程过程应该正确处理异常并在基础套接字连接关闭时停止循环。