自己琢磨Socket剛剛幾天,所以整理出來和大家共享一下。廢話少說直接進入正題。
在C#中提供了兩種網絡服務,一種是Socket類,另一種是TcpListener(服務器),TcpClient(客戶端);
至於這兩種有什麼區別那;MSDN上是這樣解釋的:
TcpClient 類,TcpListener 類提供了一些簡單的方法,用於在同步阻止模式下通過網絡來連接、發送和接收流數據。
Socket 類為網絡通信提供了一套豐富的方法和屬性。 Socket 類允許您使用 ProtocolType 枚舉中所列出的任何一種協議執行異步和同步數據傳輸。
個人理解就是一個是用於簡單的業務,一種用於復雜的業務。所以感覺是一樣的。本文事例主要用Socket類來實現。一般來說復雜的會了,簡單的應該也差不多了。
先從第一個情景來說:第一個就是建立多人聊天的模式,就是多個客戶端連接一個服務器,然後可以和多個客戶端通信。就像QQ裡的群聊。

首先我們來見一個服務器:

就包含一個文本框就行了,裡邊具體代碼如下:
1 public partial class server : Form
2 {
3 private IPEndPoint ServerInfo;//存放服務器的IP和端口信息
4 private Socket ServerSocket;//服務端運行的SOCKET
5 private Thread ServerThread;//服務端運行的線程
6 private Socket[] ClientSocket;//為客戶端建立的SOCKET連接
7 private int ClientNumb;//存放客戶端數量
8 private byte[] MsgBuffer;//存放消息數據
9
10 private object obj;
11
12 public server()
13 {
14 InitializeComponent();
15 ListenClient();
16 }
17
18 /// <summary>
19 /// 開始服務,監聽客戶端
20 /// </summary>
21 private void ListenClient()
22 {
23 try
24 {
25 ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
26 IPAddress ip = IPAddress.Parse("127.0.0.1");
27 ServerInfo = new IPEndPoint(ip, Int32.Parse("3000"));
28 ServerSocket.Bind(ServerInfo);
29 ServerSocket.Listen(10);
30
31 ClientSocket = new Socket[65535];
32 MsgBuffer = new byte[65535];
33 ClientNumb = 0;
34
35 ServerThread = new Thread(new ThreadStart(RecieveAccept));
36 ServerThread.Start();
37 }
38 catch (System.Exception ex)
39 {
40
41 }
42 }
43
44 /// <summary>
45 /// 添加阻塞,監聽客戶端
46 /// </summary>
47 private void RecieveAccept()
48 {
49 while (true)
50 {
51 //等待接受客戶端連接,如果有就執行下邊代碼,沒有就阻塞
52 ClientSocket[ClientNumb] = ServerSocket.Accept();
53 //接受客戶端信息,沒有阻塞,則會執行下邊輸出的代碼;如果是Receive則不會執行下邊輸出代碼
54 ClientSocket[ClientNumb].BeginReceive(MsgBuffer, 0, MsgBuffer.Length, SocketFlags.None,
55 new AsyncCallback(ReceiveCallback), ClientSocket[ClientNumb]);
56 this.Invoke((MethodInvoker)delegate
57 {
58 lock (this.textBox1)
59 this.textBox1.Text += "客戶端:" + ClientNumb.ToString() + "連接成功!" + "\r\n";
60 });
61 ClientNumb++;
62 }
63 }
64
65 /// <summary>
66 /// 回發數據到客戶端
67 /// </summary>
68 /// <param name="ar"></param>
69 private void ReceiveCallback(IAsyncResult ar)
70 {
71 try
72 {
73 Socket rSocket = (Socket)ar.AsyncState;
74 int rEnd = rSocket.EndReceive(ar);
75
76 for (int i = 0; i < ClientNumb; i++)
77 {
78 if (ClientSocket[i].Connected)
79 {
80 //發送數據到客戶端
81 ClientSocket[i].Send(MsgBuffer, 0, rEnd, SocketFlags.None);
82 }
83
84 //同時接受客戶端回發的數據,用於回發
85 rSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), rSocket);
86 }
87 }
88 catch (System.Exception ex)
89 {
90
91 }
92 }
93 }
然後我們添加客戶端代碼,客戶端要一個按鈕和兩個文本框

具體代碼如下:
1 public partial class Client : Form
2 {
3 private IPEndPoint ServerInfo;
4 private Socket ClientSocket;
5 private object obj;
6
7 //信息接收緩存
8 private Byte[] MsgBuffer;
9 //信息發送存儲
10 private Byte[] MsgSend;
11
12 public Client()
13 {
14 InitializeComponent();
15 ConnectServer();
16 this.button1.Click += new EventHandler(button1_Click);
17 }
18
19 /// <summary>
20 /// 打開客戶端,即連接服務器
21 /// </summary>
22 private void ConnectServer()
23 {
24 try
25 {
26 ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
27 MsgBuffer = new byte[65535];
28 MsgSend = new byte[65535];
29 IPAddress ip = IPAddress.Parse("127.0.0.1");
30 ServerInfo = new IPEndPoint(ip, Int32.Parse("3000"));
31 ClientSocket.Connect(ServerInfo);
32 //發送信息至服務器
33 ClientSocket.Send(Encoding.Unicode.GetBytes("用戶: 進入系統!" + "\r\n"));
34 ClientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, SocketFlags.None,
35 new AsyncCallback(ReceiveCallback), null);
36 this.textBox1.Text += "登錄服務器成功" + "\r\n";
37 }
38 catch (System.Exception ex)
39 {
40
41 }
42 }
43
44 /// <summary>
45 /// 回調時調用
46 /// </summary>
47 /// <param name="ar"></param>
48 private void ReceiveCallback(IAsyncResult ar)
49 {
50 int rEnd = ClientSocket.EndReceive(ar);
51 this.Invoke((MethodInvoker)delegate
52 {
53 lock (this.textBox1)
54 {
55 this.textBox1.Text += Encoding.Unicode.GetString(MsgBuffer, 0, rEnd) + "\r\n";
56 }
57 });
58 ClientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null);
59 }
60
61 /// <summary>
62 /// 發送信息
63 /// </summary>
64 /// <param name="sender"></param>
65 /// <param name="e"></param>
66 private void button1_Click(object sender, EventArgs e)
67 {
68 MsgSend = Encoding.Unicode.GetBytes("說:\n" + this.textBox2.Text + "\n\r");
69 if (ClientSocket.Connected)
70 {
71 ClientSocket.Send(MsgSend);
72 }
73 }
74
75 }
76 }
這樣先運行服務器,在多運行幾個客戶端就可以了。
下邊講一下第二種案例:這種是多個客戶端和服務器連接,每個客戶端都可以和服務器通信,但是客戶端之間沒有通信,而且每個客戶端和服務器通信時,不會影響其他客戶端。
具體樣式如圖:

接著我們來看看具體的代碼:
先來看看服務器的,樣式和第一種一樣,
具體代碼:
1 public partial class Server : Form
2 {
3 private Socket socket = null;
4 private Thread thread = null;
5
6 public Server()
7 {
8 InitializeComponent();
9 StartListening();
10 }
11
12 ///
13 /// 開始監聽客戶端
14 ///
15 private void StartListening()
16 {
17 try
18 {
19 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
20 IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
21 IPEndPoint endPoint = new IPEndPoint(ipaddress, int.Parse("3000"));
22
23 socket.Bind(endPoint);
24 socket.Listen(20);
25
26 thread = new Thread(new ThreadStart(WatchConnection));
27 thread.IsBackground = true;
28 thread.Start();
29
30 this.listBox1.Text = "開始監聽客戶端傳來的消息" + "\r\n";
31 }
32 catch (System.Exception ex)
33 {
34 this.listBox1.Text += "SocketException" + ex;
35 }
36 }
37
38 Socket[] socConnection = new Socket[12];
39 private static int clientNum = 0;
40
41 /// <summary>
42 /// 監聽客戶端發來的請求
43 /// </summary>
44 private void WatchConnection()
45 {
46 while (true)
47 {
48 socConnection[clientNum] = socket.Accept();
49 this.Invoke((MethodInvoker)delegate
50 {
51 this.listBox1.Text += "客戶端連接成功" + "\r\n";
52 });
53
54 Thread thread = new Thread(new ParameterizedThreadStart(ServerRecMsg));
55 thread.IsBackground = true;
56 thread.Start(socConnection[clientNum]);
57 clientNum++;
58 }
59 }
60
61 /// <summary>
62 /// 接受客戶端消息並發送消息
63 /// </summary>
64 /// <param name="socketClientPara"></param>
65 private void ServerRecMsg(object socketClientPara)
66 {
67 Socket socketServer = socketClientPara as Socket;
68 try
69 {
70 while (true)
71 {
72 byte[] arrServerRecMsg = new byte[1024 * 1024];
73 int length = socketServer.Receive(arrServerRecMsg);
74
75 string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
76 this.Invoke((MethodInvoker)delegate
77 {
78 this.listBox1.Text += "接收到:" + strSRecMsg + "\r\n";
79 });
80
81 byte[] arrSendMsg = Encoding.UTF8.GetBytes("收到服務器發來的消息");
82 //發送消息到客戶端
83 socketServer.Send(arrSendMsg);
84 }
85 }
86 catch (System.Exception ex)
87 {
88
89 }
90 }
91 }
再來看看客戶端代碼:
樣式和第一種也一樣:
1 public partial class Client : Form
2 {
3 private Socket socketClient = null;
4 private Thread threadClient = null;
5
6 public Client()
7 {
8 InitializeComponent();
9 ConnectionServer();
10 this.button1.Click += new EventHandler(button1_Click);
11 }
12
13 /// <summary>
14 /// 連接服務器
15 /// </summary>
16 private void ConnectionServer()
17 {
18 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
19 IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
20 IPEndPoint endPoint = new IPEndPoint(ipaddress, int.Parse("3000"));
21 try
22 {
23 socketClient.Connect(endPoint);
24 threadClient = new Thread(RecMsg);
25 threadClient.IsBackground = true;
26 threadClient.Start();
27 }
28 catch (System.Exception ex)
29 {
30
31 }
32
33 }
34
35 /// <summary>
36 /// 接收服務器消息
37 /// </summary>
38 private void RecMsg()
39 {
40 while (true)
41 {
42 //內存緩沖區1M,用於臨時存儲接收到服務器端的消息
43 byte[] arrRecMsg = new byte[1024 * 1024];
44 //將接收到的數據放入內存緩沖區,獲取其長度
45 int length = socketClient.Receive(arrRecMsg);
46 //將套接字獲取到的字節數組轉換為我們可以理解的字符串
47 string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
48 this.Invoke((MethodInvoker)delegate
49 {
50 lock (this.listBox1)
51 {
52 this.listBox1.Text += "服務器:" + strRecMsg + "\r\n";
53 }
54 });
55 }
56 }
57
58 /// <summary>
59 /// 向服務器發送消息
60 /// </summary>
61 /// <param name="sender"></param>
62 /// <param name="e"></param>
63 private void button1_Click(object sender, EventArgs e)
64 {
65 ClientSendMsg(this.textBox1.Text.Trim());
66 }
67
68 /// <summary>
69 /// 發送信息到服務器
70 /// </summary>
71 /// <param name="sendMsg"></param>
72 private void ClientSendMsg(string sendMsg)
73 {
74 //將輸入的字符串轉化為機器可以識別的字節數組
75 byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
76 //發送數據
77 socketClient.Send(arrClientSendMsg);
78 this.listBox1.Text += "客戶端:" + sendMsg + "\r\n";
79 }
80 }
到此兩種方式就說完了,不知道說的對不對,請各位吐槽!!!,轉載注明出處。
main()
{
int i,j,temp;
int a[10];
for(i=0;i<10;i++)
scanf ("%d,",&a[i]);
for(j=0;j<=9;j++)
{ for (i=0;i<10-j;i++)
if (a[i]>a[i+1])
{ temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;}
}
for(i=1;i<11;i++)
printf("%5d,",a[i] );
printf("\n");
}
--------------
冒泡算法
冒泡排序的算法分析與改進
交換排序的基本思想是:兩兩比較待排序記錄的關鍵字,發現兩個記錄的次序相反時即進行交換,直到沒有反序的記錄為止。
應用交換排序基本思想的主要排序方法有:冒泡排序和快速排序。
冒泡排序
1、排序方法
將被排序的記錄數組R[1..n]垂直排列,每個記錄R看作是重量為R.key的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R:凡掃描到違反本原則的輕氣泡,就使其向上"飄浮"。如此反復進行,直到最後任何兩個氣泡都是輕者在上,重者在下為止。
(1)初始
R[1..n]為無序區。
(2)第一趟掃描
從無序區底部向上依次比較相鄰的兩個氣泡的重量,若發現輕者在下、重者在上,則交換二者的位置。即依次比較(R[n],R[n-1]),(R[n-1],R[n-2]),…,(R[2],R[1]);對於每對氣泡(R[j+1],R[j]),若R[j+1].key<R[j].key,則交換R[j+1]和R[j]的內容。
第一趟掃描完畢時,"最輕"的氣泡就飄浮到該區間的頂部,即關鍵字最小的記錄被放在最高位置R[1]上。
(3)第二趟掃描
掃描R[2..n]。掃描完畢時,"次輕"的氣泡飄浮到R[2]的位置上……
最後,經過n-1 趟掃描可得到有序區R[1..n]
注意:
第i趟掃描時,R[1..i-1]和R[i..n]分別為當前的有序區和無序區。掃描仍是從無序區底部向上直至該區頂部。掃描完畢時,該區中最輕氣泡飄浮到頂部位置R上,結果是R[1..i]變為新的有序區。
2、冒泡排序過程示例
對關鍵字序列為49 38 65 97 76 13 27 49的文件進行冒泡排序的過程
3、排序算法
(1)分析
因為每一趟排序都使有序區增加了一個氣泡,在經過n-1趟排序之後,有序區中就有n-1個氣泡,而無序區中氣泡的重量總是大於等於有序區中氣泡的重量,所以整個冒泡排序過程至多需要進行n-1趟排序。
若在某一趟排序中未發現氣泡位置的交換,則說明待排序的無序區中所有氣泡均滿足輕者在上,重者在下的原則,因此,冒泡排序過程可在此趟排序後終止。為此,在下面給出的算法中,引入一個布爾量exchange,在每趟排序開始前,先將其置為FALSE。若排序過程中發生了交換,則將其置為TRUE。各趟排序結束時檢查exchange,若未曾發生過交換則終止算法,不再進行下一趟排序。
(2)具體算法
void BubbleSort(SeqList R)
{ //R(l..n)是待排序的文件,采用自下向上掃描,對R做冒泡排序
int i,j;
Boolean exchange; //交換標志
for(i=1;i&......余下全文>>
main()
{
int i,j,temp;
int a[10];
for(i=0;i<10;i++)
scanf ("%d,",&a[i]);
for(j=0;j<=9;j++)
{ for (i=0;i<10-j;i++)
if (a[i]>a[i+1])
{ temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;}
}
for(i=1;i<11;i++)
printf("%5d,",a[i] );
printf("\n");
}
--------------
冒泡算法
冒泡排序的算法分析與改進
交換排序的基本思想是:兩兩比較待排序記錄的關鍵字,發現兩個記錄的次序相反時即進行交換,直到沒有反序的記錄為止。
應用交換排序基本思想的主要排序方法有:冒泡排序和快速排序。
冒泡排序
1、排序方法
將被排序的記錄數組R[1..n]垂直排列,每個記錄R看作是重量為R.key的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R:凡掃描到違反本原則的輕氣泡,就使其向上"飄浮"。如此反復進行,直到最後任何兩個氣泡都是輕者在上,重者在下為止。
(1)初始
R[1..n]為無序區。
(2)第一趟掃描
從無序區底部向上依次比較相鄰的兩個氣泡的重量,若發現輕者在下、重者在上,則交換二者的位置。即依次比較(R[n],R[n-1]),(R[n-1],R[n-2]),…,(R[2],R[1]);對於每對氣泡(R[j+1],R[j]),若R[j+1].key<R[j].key,則交換R[j+1]和R[j]的內容。
第一趟掃描完畢時,"最輕"的氣泡就飄浮到該區間的頂部,即關鍵字最小的記錄被放在最高位置R[1]上。
(3)第二趟掃描
掃描R[2..n]。掃描完畢時,"次輕"的氣泡飄浮到R[2]的位置上……
最後,經過n-1 趟掃描可得到有序區R[1..n]
注意:
第i趟掃描時,R[1..i-1]和R[i..n]分別為當前的有序區和無序區。掃描仍是從無序區底部向上直至該區頂部。掃描完畢時,該區中最輕氣泡飄浮到頂部位置R上,結果是R[1..i]變為新的有序區。
2、冒泡排序過程示例
對關鍵字序列為49 38 65 97 76 13 27 49的文件進行冒泡排序的過程
3、排序算法
(1)分析
因為每一趟排序都使有序區增加了一個氣泡,在經過n-1趟排序之後,有序區中就有n-1個氣泡,而無序區中氣泡的重量總是大於等於有序區中氣泡的重量,所以整個冒泡排序過程至多需要進行n-1趟排序。
若在某一趟排序中未發現氣泡位置的交換,則說明待排序的無序區中所有氣泡均滿足輕者在上,重者在下的原則,因此,冒泡排序過程可在此趟排序後終止。為此,在下面給出的算法中,引入一個布爾量exchange,在每趟排序開始前,先將其置為FALSE。若排序過程中發生了交換,則將其置為TRUE。各趟排序結束時檢查exchange,若未曾發生過交換則終止算法,不再進行下一趟排序。
(2)具體算法
void BubbleSort(SeqList R)
{ //R(l..n)是待排序的文件,采用自下向上掃描,對R做冒泡排序
int i,j;
Boolean exchange; //交換標志
for(i=1;i&......余下全文>>