2013年4月23日 星期二

C#顏色和名稱樣式對照表


以下的顏色代碼取自HTML規範,這些顏色的名稱對應於KnownColor的屬性。比如,你可以用以下代碼來創建一個Color對象:
Color c = Color.FromKnownColor(KnownColor.colorname);
所有的colorname在後面的表格中一一列出,這些顏色對應的RGB值列在名字的後面,你可以使用FromArgb方法來創建Color對象。以下兩行實際上創建了同一種顏色:
Color c1 = Color.FromArgb(32,178,170);
Color c2 = Color.FromKnownColor(KnownColor.LightSeaGreen);
在下面這張表中,我嚴格依照顏色的RGB值設置對應顏色的顯示。你所看到的真實效果依賴於瀏覽器是否準確處理了對應24位色的顏色顯示(一些瀏覽器可能將某些顏色映射成“最接近的網頁調色板顏色”),顯示器的調節或者你顯卡的校正值。因此顯示效果會略有不同。
補充:
還有一些獲取顏色的方式:
Color c1 = Color.AliceBlue;            //Color類自帶的靜態顏色對象Color c2 = Color.FromArgb(0x20B2AA);   //網頁裏面提取的顏色(原格式為#20B2AA)
C#顏色和名稱對照表
A B C D E F G H I J K L M 
N O P Q R S T U V W X Y Z
1 
Color.AliceBlue
240,248,255
Color.LightSalmon
255,160,122
Color.AntiqueWhite
250,235,215
Color.LightSeaGreen
32,178,170
Color.Aqua
0,255,255
Color.LightSkyBlue
135,206,250
Color.Aquamarine
127,255,212
Color.LightSlateGray
119,136,153
Color.Azure
240,255,255
Color.LightSteelBlue
176,196,222
Color.Beige
245,245,220
Color.LightYellow
255,255,224
Color.Bisque
255,228,196
Color.Lime
0,255,0
Color.Black
0,0,0
Color.LimeGreen
50,205,50
Color.BlanchedAlmond
255,255,205
Color.Linen
250,240,230
Color.Blue
0,0,255
Color.Magenta
255,0,255
Color.BlueViolet
138,43,226
Color.Maroon
128,0,0
Color.Brown
165,42,42
Color.MediumAquamarine
102,205,170
Color.BurlyWood
222,184,135
Color.MediumBlue
0,0,205
Color.CadetBlue
95,158,160
Color.MediumOrchid
186,85,211
Color.Chartreuse
127,255,0
Color.MediumPurple
147,112,219
Color.Chocolate
210,105,30
Color.MediumSeaGreen
60,179,113
Color.Coral
255,127,80
Color.MediumSlateBlue
123,104,238
Color.CornflowerBlue
100,149,237
Color.MediumSpringGreen
0,250,154
Color.Cornsilk
255,248,220
Color.MediumTurquoise
72,209,204
Color.Crimson
220,20,60
Color.MediumVioletRed
199,21,112
Color.Cyan
0,255,255
Color.MidnightBlue
25,25,112
Color.DarkBlue
0,0,139
Color.MintCream
245,255,250
Color.DarkCyan
0,139,139
Color.MistyRose
255,228,225
Color.DarkGoldenrod
184,134,11
Color.Moccasin
255,228,181
Color.DarkGray
169,169,169
Color.NavajoWhite
255,222,173
Color.DarkGreen
0,100,0
Color.Navy
0,0,128
Color.DarkKhaki
189,183,107
Color.OldLace
253,245,230
Color.DarkMagena
139,0,139
Color.Olive
128,128,0
Color.DarkOliveGreen
85,107,47
Color.OliveDrab
107,142,45
Color.DarkOrange
255,140,0
Color.Orange
255,165,0
Color.DarkOrchid
153,50,204
Color.OrangeRed
255,69,0
Color.DarkRed
139,0,0
Color.Orchid
218,112,214
Color.DarkSalmon
233,150,122
Color.PaleGoldenrod
238,232,170
Color.DarkSeaGreen
143,188,143
Color.PaleGreen
152,251,152
Color.DarkSlateBlue
72,61,139
Color.PaleTurquoise
175,238,238
Color.DarkSlateGray
40,79,79
Color.PaleVioletRed
219,112,147
Color.DarkTurquoise
0,206,209
Color.PapayaWhip
255,239,213
Color.DarkViolet
148,0,211
Color.PeachPuff
255,218,155
Color.DeepPink
255,20,147
Color.Peru
205,133,63
Color.DeepSkyBlue
0,191,255
Color.Pink
255,192,203
Color.DimGray
105,105,105
Color.Plum
221,160,221
Color.DodgerBlue
30,144,255
Color.PowderBlue
176,224,230
Color.Firebrick
178,34,34
Color.Purple
128,0,128
Color.FloralWhite
255,250,240
Color.Red
255,0,0
Color.ForestGreen
34,139,34
Color.RosyBrown
188,143,143
Color.Fuschia
255,0,255
Color.RoyalBlue
65,105,225
Color.Gainsboro
220,220,220
Color.SaddleBrown
139,69,19
Color.GhostWhite
248,248,255
Color.Salmon
250,128,114
Color.Gold
255,215,0
Color.SandyBrown
244,164,96
Color.Goldenrod
218,165,32
Color.SeaGreen
46,139,87
Color.Gray
128,128,128
Color.Seashell
255,245,238
Color.Green
0,128,0
Color.Sienna
160,82,45
Color.GreenYellow
173,255,47
Color.Silver
192,192,192
Color.Honeydew
240,255,240
Color.SkyBlue
135,206,235
Color.HotPink
255,105,180
Color.SlateBlue
106,90,205
Color.IndianRed
205,92,92
Color.SlateGray
112,128,144
Color.Indigo
75,0,130
Color.Snow
255,250,250
Color.Ivory
255,240,240
Color.SpringGreen
0,255,127
Color.Khaki
240,230,140
Color.SteelBlue
70,130,180
Color.Lavender
230,230,250
Color.Tan
210,180,140
Color.LavenderBlush
255,240,245
Color.Teal
0,128,128
Color.LawnGreen
124,252,0
Color.Thistle
216,191,216
Color.LemonChiffon
255,250,205
Color.Tomato
253,99,71
Color.LightBlue
173,216,230
Color.Turquoise
64,224,208
Color.LightCoral
240,128,128
Color.Violet
238,130,238
Color.LightCyan
224,255,255
Color.Wheat
245,222,179
Color.LightGoldenrodYellow
250,250,210
Color.White
255,255,255
Color.LightGreen
144,238,144
Color.WhiteSmoke
245,245,245
Color.LightGray
211,211,211
Color.Yellow
255,255,0
Color.LightPink
255,182,193
Color.YellowGreen
154,205,50

2013年4月7日 星期日

C#程式中寫LOG


在開發程式的過程中,可能為了除錯方便,需要將執行的過程記錄到LOG檔案中,這樣的東西應該是大家所共有的方法。而且這樣的動作在每個地方都會發生,所以應該寫一個公用的物件來處理這件事情。
   1: public static class EventLog {
   2:     public static string FilePath { get; set; }
   3:  
   4:     public static void Write(string format, params object[] arg) {
   5:         Write(string.Format(format, arg));
   6:     }
   7:  
   8:     public static void Write(string message) {
   9:         if (string.IsNullOrEmpty(FilePath)) {
  10:             FilePath = Directory.GetCurrentDirectory();
  11:         }
  12:         string filename = FilePath + 
  13:             string.Format("\\{0:yyyy}\\{0:MM}\\{0:yyyy-MM-dd}.txt", DateTime.Now);
  14:         FileInfo finfo = new FileInfo(filename);
  15:         if (finfo.Directory.Exists == false) {
  16:             finfo.Directory.Create();
  17:         }
  18:         string writeString = string.Format("{0:yyyy/MM/dd HH:mm:ss} {1}", 
  19:             DateTime.Now, message) + Environment.NewLine;
  20:         File.AppendAllText(filename, writeString, Encoding.Unicode);
  21:     }
  22: }

其中第12行是將檔案依照/年/月/年-月-日.txt的方式設定檔案名稱,第15行使用這個檔案名稱的路徑部份建立資料夾。FileInfo的資料夾建立功能是可以直接建立子資料夾的,網上有些程式還很費力的一層層判斷、建立,那是錯的。
第4行是個多型,其實只是套用string.Format,我很多時候都會多寫一個這樣的多型方法,可以讓使用的程式碼再簡潔一點。

2013年4月2日 星期二

C# Tutorial - Simple Threaded TCP Server


In this tutorial I'm going to show you how to build a threaded tcp server with C#. If you've ever worked with Window's sockets, you know how difficult this can sometimes be. However, thanks to the .NET framework, making one is a lot easier than it used to be.
What we'll be building today is a very simple server that accepts client connections and can send and receive data. The server spawns a thread for each client and can, in theory, accept as many connections as you want (although in practice this is limited because you can only spawn so many threads before Windows will get upset).

Let's just jump into some code. Below is the basic setup for our TCP server class.
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TCPServerTutorial
{
  class Server
  {
    private TcpListener tcpListener;
    private Thread listenThread;

    public Server()
    {
      this.tcpListener = new TcpListener(IPAddress.Any, 3000);
      this.listenThread = new Thread(new ThreadStart(ListenForClients));
      this.listenThread.Start();
    }
  }
}
So here's a basic server class - without the guts. We've got a TcpListener which does a good job of wrapping up the underlying socket communication, and a Thread which will be listening for client connections. You might have noticed the function ListenForClients that is used for our ThreadStart delegate. Let's see what that looks like.
private void ListenForClients()
{
  this.tcpListener.Start();

  while (true)
  {
    //blocks until a client has connected to the server
    TcpClient client = this.tcpListener.AcceptTcpClient();

    //create a thread to handle communication 
    //with connected client
    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
    clientThread.Start(client);
  }
}
This function is pretty simple. First it starts our TcpListener and then sits in a loop accepting connections. The call to AcceptTcpClient will block until a client has connected, at which point we fire off a thread to handle communication with our new client. I used a ParameterizedThreadStart delegate so I could pass theTcpClient object returned by the AcceptTcpClient call to our new thread.
The function I used for the ParameterizedThreadStart is called HandleClientComm. This function is responsible for reading data from the client. Let's have a look at it.
private void HandleClientComm(object client)
{
  TcpClient tcpClient = (TcpClient)client;
  NetworkStream clientStream = tcpClient.GetStream();

  byte[] message = new byte[4096];
  int bytesRead;

  while (true)
  {
    bytesRead = 0;

    try
    {
      //blocks until a client sends a message
      bytesRead = clientStream.Read(message, 0, 4096);
    }
    catch
    {
      //a socket error has occured
      break;
    }

    if (bytesRead == 0)
    {
      //the client has disconnected from the server
      break;
    }

    //message has successfully been received
    ASCIIEncoding encoder = new ASCIIEncoding();
    System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
  }

  tcpClient.Close();
}
The first thing we need to do is cast client as a TcpClient object since the ParameterizedThreadStart delegate can only accept object types. Next, we get the NetworkStream from the TcpClient, which we'll be using to do our reading. After that we simply sit in a while true loop reading information from the client. TheRead call will block indefinitely until a message from the client has been received. If you read zero bytes from the client, you know the client has disconnected. Otherwise, a message has been successfully received from the server. In my example code, I simply convert the byte array to a string and push it to the debug console. You will, of course, do something more interesting with the data - I hope. If the socket has an error or the client disconnects, you should call Close on the TcpClient object to free up any resources it was using.
Believe it or not, that's pretty much all you need to do to create a threaded server that accepts connections and reads data from clients. However, a server isn't very useful if it can't send data back, so let's look at how to send data to one of our connected clients.
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
Do you remember the TcpClient object that was returned from the call AcceptTcpClient? Well, that's the object we'll be using to send data back to that client. That being said, you'll probably want to keep those objects around somewhere in your server. I usually keep a collection of TcpClient objects that I can use later. Sending data to connected clients is very simple. All you have to do is call Write on the the client's NetworkStream object and pass it the byte array you'd like to send.
Your TCP server is now finished. The hard part is defining a good protocol to use for sending information between the client and server. Application level protocols are generally unique for application, so I'm not going to go into any details - you'll just have to invent you're own.
But what use is a server without a client to connect to it? This tutorial is mainly about the server, but here's a quick piece of code that shows you how to set up a basic TCP connection and send it a piece of data.
TcpClient client = new TcpClient();

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
The first thing we need to do is get the client connected to the server. We use the TcpClient.Connect method to do this. It needs the IPEndPoint of our server to make the connection - in this case I connect it to localhost on port 3000. I then simply send the server the string "Hello Server!".
One very important thing to remember is that one write from the client or server does not always equal one read on the receiving end. For instance, your client could send 10 bytes to the server, but the server may not get all 10 bytes the first time it reads. Using TCP, you're pretty much guaranteed to eventually get all 10 bytes, but it might take more than one read. You should keep that in mind when designing your protocol.
That's it! Now get out there and clog the tubes with your fancy new C# TCP servers.