1. 程式人生 > >C# Socket網絡編程實例

C# Socket網絡編程實例

文件 null component art oid ddr 部署圖 image 函數名

本文實例講述了C# Socket網絡編程技巧。分享給大家供大家參考。具體分析如下:

客戶端要連接服務器:首先要知道服務器的IP地址。而服務器裏有很多的應用程序,每一個應用程序對應一個端口號

所以客戶端想要與服務器中的某個應用程序進行通信就必須要知道那個應用程序的所在服務器的IP地址,及應用程序所對應的端口號


TCP協議:

安全穩定,一般不會發生數據丟失,但是效率低。利用TCP發生數據一般經過3次握手(所有效率低,自己百度三次握手)


UDP協議:

快速,效率高,但是不穩定,容易發生數據丟失(沒有經過三次握手,不管服務器有空沒空,信息全往服務器發,所有效率搞,但服務器忙的時候就沒辦法處理你的數據,容易造成數據丟失,不穩定)


代碼如下:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Net.Sockets;

using System.Net;

using System.Threading;

namespace Socket通信

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

this.txtPort.Text = “5000”;

this.txtIp.Text = “192.168.137.1”;

}

private void btnStart_Click(object sender, EventArgs e)

{

//當點擊開始監聽的時候,在服務器端創建一個負責監聽IP地址跟端口號的Socket

Socket socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

//Any:提供一個 IP 地址,指示服務器應偵聽所有網絡接口上的客戶端活動。此字段為只讀。

IPAddress ip = IPAddress.Any;

//創建端口號對象;將txtPort.Text控件的值設為服務端的端口號

IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));

//監聽

socketWatch.Bind(point);

ShowMsg(“監聽成功”);

socketWatch.Listen(10);//連接隊列的最大長度 ;即:一個時間點內最大能讓幾個客戶端連接進來,超過長度就進行排隊

//等待客戶端連接;Accept()這個方法能接收客戶端的連接,並為新連接創建一個負責通信的Socket

Thread th = new Thread(Listen); //被線程執行的方法如果有參數的話,參數必須是object類型

Control.CheckForIllegalCrossThreadCalls = false; //因為.net不允許跨線程訪問的,所以這裏取消跨線程的檢查。.net不檢查是否有跨線程訪問了,所有就不會報: “從不是創建控件“txtLog”的線程訪問它” 這個錯誤了,從而實現了跨線程訪問

th.IsBackground = true; //將th這個線程設為後臺線程。

//Start(object parameter); parameter:一個對象,包含線程執行的方法要使用的數據,即線程執行Listen方法,Listen的參數

th.Start(socketWatch); //這個括號裏的參數其實是Listen()方法的參數。因為Thread th = new Thread(Listen)這個括號裏只能寫方法名(函數名) 但是Listen()方法是有參數的,所有就要用Start()方法將它的參數添加進來

}

/// <summary>

/// 等待客戶端連接,如果監控到有客戶端連接進來就創建一個與之通信的Socket

/// </summary>

/// <param name=”o”></param>

void Listen(object o) //這裏為什麽不直接傳遞Socket類型的參數呢? 原因是:被線程執行的方法如果有參數的話,參數必須是object類型

{

Socket socketWatch = o as Socket;

while (true) //為什麽這裏要有個while循環?因為當一個人連接進來的時候創建了與之通信的Socket後就程序就會往下執行了,就不會再回來為第二個人的連接創建負責通信的Socket了。(應該是每個人(每個客戶端)創建一個與之通信的Socket)所以要寫在循環裏。

{

//等待客戶端連接;Accept()這個方法能接收客戶端的連接,並為新連接創建一個負責通信的Socket

Socket socketSend = socketWatch.Accept();

dic.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //(根據客戶端的IP地址和端口號找負責通信的Socket,每個客戶端對應一個負責通信的Socket),ip地址及端口號作為鍵,將負責通信的Socket作為值填充到dic鍵值對中。

//我們通過負責通信的這個socketSend對象的一個RemoteEndPoint屬性,能夠拿到遠程連過來的客戶端的Ip地址跟端口號

ShowMsg(socketSend.RemoteEndPoint.ToString() + “:” + “連接成功”);//效果:192.168.1.32:連接成功

comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString()); //將連接過來的每個客戶端都添加到combBox控件中。

//客戶端連接成功後,服務器應該接收客戶端發來的消息。

Thread getdata = new Thread(GetData);

getdata.IsBackground = true;

getdata.Start(socketSend);

}

}

Dictionary<string, Socket> dic = new Dictionary<string, Socket>();

/// <summary>

/// 不停的接收客戶端發送過來的消息

/// </summary>

/// <param name=”o”></param>

void GetData(object o)

{

while (true)

{

Socket socketSend = o as Socket;

//將客戶端發過來的數據先放到一個字節數組裏面去

byte[] buffer = new byte[1024 * 1024 * 2]; //創建一個字節數組,字節數組的長度為2M

//實際接收到的有效字節數; (利用Receive方法接收客戶端傳過來的數據,然後把數據保存到buffer字節數組中,返回一個接收到的數據的長度)

int r = socketSend.Receive(buffer);

if (r == 0) //如果接收到的有效字節數為0 說明客戶端已經關閉了。這時候就跳出循環了。

{

//只有客戶端給用戶發消息,不可能是發0個長度的字節。即便發空消息,空消息也是有過個長度的。所有接收到的有效字節長度為0就代表客戶端已經關閉了

break;

}

//將buffer這個字節數組裏面的數據按照UTF8的編碼,解碼成我們能夠讀懂的的string類型,因為buffer這個數組的實際存儲數據的長度是r個 ,所以從索引為0的字節開始解碼,總共解碼r個字節長度。

string str = Encoding.UTF8.GetString(buffer, 0, r);

ShowMsg(socketSend.RemoteEndPoint.ToString() + “:” + str);

}

}

private void ShowMsg(string str)

{

txtLog.AppendText(str + “\r\n”); //將str這個字符串添加到txtLog這個文本框中。

}

/// <summary>

/// 服務端給客戶端發信息

/// </summary>

/// <param name=”sender”></param>

/// <param name=”e”></param>

private void btnSend_Click_1(object sender, EventArgs e)

{

if (comboBox1.SelectedItem == null) //如果comboBox控件沒有選中值。就提示用戶選擇客戶端

{

MessageBox.Show(“請選擇客戶端”);

return;

}

string str = txtMes.Text; //獲取用戶輸入的內容 (服務端要給客戶端發的信息)

byte[] strByte = Encoding.Default.GetBytes(str); //將信息轉換成二進制字節數組

string getIp = comboBox1.SelectedItem as string; //comboBox存儲的是客戶端的(ip+端口號)

Socket socketSend = dic[getIp] as Socket; //根據這個(ip及端口號)去dic鍵值對中找對應 賦值與客戶端通信的Socket【每個客戶端都有一個負責與之通信的Socket】

socketSend.Send(strByte); //將信息發送到客戶端

}

}

}

開打開始命令 cmd telnet 10.18.16.46 5000 即telnet 服務器ip地址 綁定的端口號

希望本文所述對大家的C#程序設計有所幫助。

除聲明外,跑步客文章均為原創,轉載請以鏈接形式標明本文地址
C# Socket網絡編程實例

本文地址: http://www.paobuke.com/develop/c-develop/pbk23169.html






相關內容

技術分享圖片VS2012 程序打包部署圖文詳解技術分享圖片解析C#設計模式編程中備忘錄模式的運用技術分享圖片C#通過流寫入數據到文件的方法技術分享圖片C#、ASP.NET通用擴展工具類之TypeParse
技術分享圖片C#中數組段用法實例分析技術分享圖片C#???ú×a·¢ó?·¨?ê?a技術分享圖片C#特性-對象集合初始化器介紹技術分享圖片DevExpress實現為TextEdit設置水印文字的方法

C# Socket網絡編程實例