1. 程式人生 > >C#完整的通訊程式碼(點對點,點對多,同步,非同步,UDP,TCP)

C#完整的通訊程式碼(點對點,點對多,同步,非同步,UDP,TCP)

C# code

namespace UDPServer

{

class Program

{

static void Main(string[] args)

{

int recv;

byte[] data = new byte[1024];

//構建TCP 伺服器

//得到本機IP,設定TCP埠號

IPEndPoint ipep = new IPEndPoint(IPAddress.Any , 8001);

Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram , ProtocolType.Udp);

//繫結網路地址

newsock.Bind(ipep);

Console.WriteLine("This is a Server, host name is {0}",Dns.GetHostName());

//等待客戶機連線

Console.WriteLine("Waiting for a client...");

//得到客戶機IP

IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);

EndPoint Remote = (EndPoint)(sender);

recv = newsock.ReceiveFrom(data, ref Remote);

Console .WriteLine ("Message received from {0}: ", Remote.ToString ());

Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv ));

//客戶機連線成功後,傳送歡迎資訊

string welcome = "Welcome ! ";

//字串與位元組陣列相互轉換

data = Encoding .ASCII .GetBytes (welcome );

//傳送資訊

newsock .SendTo (data ,data.Length ,SocketFlags .None ,Remote );

while (true )

{

data =new byte [1024];

//傳送接受資訊

recv =newsock.ReceiveFrom(data ,ref Remote);

Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv));

newsock .SendTo (data ,recv ,SocketFlags .None ,Remote );

}

}

}

}

C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPClient
{
class Program
{
static void Main(string[] args)
{
byte[] data = new byte[1024];
string input ,stringData;
//構建TCP 伺服器
Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());
//設定服務IP,設定TCP埠號
IPEndPoint ipep = new IPEndPoint(IPAddress .Parse ("127.0.0.1") , 8001);
//定義網路型別,資料連線型別和網路協議UDP
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello! ";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint Remote = (EndPoint)sender;
data = new byte[1024];
int recv = server.ReceiveFrom(data, ref Remote);
Console.WriteLine("Message received from {0}: ", Remote.ToString());
Console.WriteLine(Encoding .ASCII .GetString (data,0,recv));
while (true)
{
input = Console .ReadLine ();
if (input =="exit")
break ;
server .SendTo (Encoding .ASCII .GetBytes (input ),Remote );
data = new byte [1024];
recv = server.ReceiveFrom(data, ref Remote);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
}
Console .WriteLine ("Stopping Client.");
server .Close ();
}
}
}

C# code
TCPClient
TCPClient 類提供了一種使用 TCP 協議連線到某個端點的簡化方法。它還通過 NetworkStream 物件展現在連線過程中讀取或寫入的資料。請參見下面從 QuickStart 文件中摘錄的日期/時間客戶機示例。
使用 C# 編寫
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
class Client
{
public static void Main(String[] args)
{
TCPClient tcpc = new TCPClient();
Byte[] read = new Byte[32];
if (args.Length != 1)
{
Console.WriteLine(“請在命令列中指定伺服器名稱”);
return;
}
String server = args[0];
// 驗證伺服器是否存在
if (DNS.GetHostByName(server) == null)
{
Console.WriteLine(“找不到伺服器:” + 伺服器);
return;
}
// 嘗試連線到伺服器
if (tcpc.Connect(server, 13) == -1)
{
Console.WriteLine(“無法連線到伺服器:” + 伺服器);
return;
}
// 獲取流
Stream s = tcpc.GetStream();
// 讀取流並將它轉換為 ASCII 碼形式
int bytes = s.Read(read, 0, read.Length);
String Time = Encoding.ASCII.GetString(read);
// 顯示資料
Console.WriteLine(“已接收到的” + 位元組 + “位元組”);
Console.WriteLine(“當前日期和時間是:” + 時間);
tcpc.Close();
}
}
TCPListener
TCPListener 類便於在來自某個客戶機的 TCP 連線的特定套接字上進行偵聽的工作。請參見下面包括在 QuickStart 文件中的日期/時間伺服器示例。
使用 C# 編寫
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class Server
{
public static void Main()
{
DateTime now;
String strDateLine;
Encoding ASCII = Encoding.ASCII;
// 在埠 13 進行偵聽
TCPListener tcpl = new TCPListener(13);
tcpl.Start();
Console.WriteLine(“正在等待客戶進行連線”);
Console.WriteLine(“請按 Ctrl+c 退出...”);
while (true)
{
// 接收會阻塞,直到有人連線上
Socket s = tcpl.Accept();
// 獲取當前的日期和時間並將它連線成一個字串
now = DateTime.Now;
strDateLine = now.ToShortDateString() + " " +
now.ToLongTimeString();
// 將該字串轉換成一個位元組陣列併發送它
Byte[] byteDateLine =
ASCII.GetBytes(strDateLine.ToCharArray());
s.Send(byteDateLine, byteDateLine.Length, 0);
Console.WriteLine(“傳送” + strDateLine);
}
}
}

#region "Download: File transfer FROM ftp server"
/// <summary>
/// Copy a file from FTP server to local
/// </summary>
/// <param name="sourceFilename">Target filename, if required </param>
/// <param name="localFilename">Full path of the local file </param>
/// <returns> </returns>
/// <remarks>Target can be blank (use same filename), or just a filename
/// (assumes current directory) or a full path and filename </remarks>
public bool Download(string sourceFilename, string localFilename, bool PermitOverwrite)
{
//2. determine target file
FileInfo fi = new FileInfo(localFilename);
return this.Download(sourceFilename, fi, PermitOverwrite);
}
//Version taking an FtpFileInfo
public bool Download(FtpFileInfo file, string localFilename, bool permitOverwrite)
{
return this.Download(file.FullName, localFilename, permitOverwrite);
}
//Another version taking FtpFileInfo and FileInfo
public bool Download(FtpFileInfo file, FileInfo localFI, bool permitOverwrite)
{
return this.Download(file.FullName, localFI, permitOverwrite);
}
//Version taking string/FileInfo
public bool Download(string sourceFilename, FileInfo targetFI, bool permitOverwrite)
{
//1. check target
if (targetFI.Exists && !(permitOverwrite))
{
throw (new ApplicationException("Target file already exists"));
}
//2. check source
string target;
if (sourceFilename.Trim() == "")
{
throw (new ApplicationException("File not specified"));
}
else if (sourceFilename.Contains("/"))
{
//treat as a full path
target = AdjustDir(sourceFilename);
}
else
{
//treat as filename only, use current directory
target = CurrentDirectory + sourceFilename;
}
string URI = Hostname + target;
//3. perform copy
System.Net.FtpWebRequest ftp = GetRequest(URI);
//Set request to download a file in binary mode
ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
ftp.UseBinary = true;
//open request and get response stream
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
//loop to read & write to file
using (FileStream fs = targetFI.OpenWrite())
{
try
{
byte[] buffer = new byte[2048];
int read = 0;
do
{
read = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, read);
} while (!(read == 0));
responseStream.Close();
fs.Flush();
fs.Close();
}
catch (Exception)
{
//catch error and delete file only partially downloaded
fs.Close();
//delete target file as it's incomplete
targetFI.Delete();
throw;
}
}
responseStream.Close();
}
response.Close();
}
return true;
}
#endregion

簡單的UDP收發.
傳送
C# code
try
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //向此網段發廣播包
int UDPListenerPort = 8082;
IPAddress broadcast = IPAddress.Parse("192.168.0.255"); //此處根據IP及子網掩碼改為相應的廣播IP
string ts = "This is UPD string for sending";
byte[] sendbuf = Encoding.ASCII.GetBytes(ts);
IPEndPoint ep = new IPEndPoint(broadcast, UDPListenerPort);
s.SendTo(sendbuf, ep);
}
catch (Exception e)
{}
接收
C# code
UdpClient listener;
int UDPListenerPort = 8082;
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, UDPListenerPort);
try
{
while (true)
{
byte[] bytes = listener.Receive(ref groupEP);
string RecIP = groupEP.ToString().Substring(0, groupEP.ToString().IndexOf(":")); //收到傳送UPD端的IP
string RecStr = Encoding.ASCII.GetString(bytes, 0, bytes.Length); //收到的UPD字串
}
}
catch
{}

C# code
TCPClient
TCPClient 類提供了一種使用 TCP 協議連線到某個端點的簡化方法。它還通過 NetworkStream 物件展現在連線過程中讀取或寫入的資料。請參見下面從 QuickStart 文件中摘錄的日期/時間客戶機示例。
使用 C# 編寫
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
class Client
{
public static void Main(String[] args)
{
TCPClient tcpc = new T…

來一個Remoting的:
C# code
using System;
namespace Remotable
{
public class RemotableType : MarshalByRefObject
{
private string _internalString = "This is the RemotableType.";
public string StringMethod()
{
return _internalString;
}
}
}
using System;
using System.Runtime.Remoting;
namespace RemotingFirst
{
public class Listener
{
public static void Main()
{
RemotingConfiguration.Configure("Listener.exe.config");
Console.WriteLine("Listening for requests. Press Enter to exit");
Console.ReadLine();
}
}
}
using System;
using System.Runtime.Remoting;
namespace Client
{
public class Client
{
public static void Main()
{
RemotingConfiguration.Configure("Client.exe.config");
Remotable.RemotableType remoteObject = new Remotable.RemotableType();
Console.WriteLine(remoteObject.StringMethod());
}
}
}
Listener.exe.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="Remotable.RemotableType, RemotableType"
objectUri="RemotableType.rem"
/>
</service>
<channels>
<channel ref="http" port="8989"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>

實只要用到Socket聯接,基本上就得使用Thread,是交叉使用的。
C#封裝的Socket用法基本上不算很複雜,只是不知道託管之後的Socket有沒有其他效能或者安全上的問題。
在C#裡面能找到的最底層的操作也就是socket了,概念不做解釋。
程式模型如下:
WinForm程式 : 啟動埠偵聽;監視Socket聯接情況;定期關閉不活動的聯接;
Listener:處理Socket的Accept函式,偵聽新連結,建立新Thread來處理這些聯接(Connection)。
Connection:處理具體的每一個聯接的會話。
1:WinForm如何啟動一個新的執行緒來啟動Listener:
//start the server
private void btn_startServer_Click(object sender, EventArgs e)
{
//this.btn_startServer.Enabled = false;
Thread _createServer = new Thread(new ThreadStart(WaitForConnect));
_createServer.Start();
}
//wait all connections
private void WaitForConnect()
{
SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));
listener.StartListening();
}
因為偵聽聯接是一個迴圈等待的函式,所以不可能在WinForm的執行緒裡面直接執行,不然Winform也就是無法繼續任何操作了,所以才指定一個新的執行緒來執行這個函式,啟動偵聽迴圈。
這一個新的執行緒是比較簡單的,基本上沒有啟動的引數,直接指定處理函式就可以了。
2:Listener如何啟動迴圈偵聽,並且啟動新的帶有引數的執行緒來處理Socket聯接會話。
先看如何建立偵聽:(StartListening函式)
IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(20);//20 trucks
// Start listening for connections.
while (true)
{
// here will be suspended while waiting for a new connection.
Socket connection = listener.Accept();
Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection
……
}
}……
基本步驟比較簡單:
建立本機的IPEndPoint物件,表示以本機為伺服器,在指定埠偵聽;
然後繫結到一個偵聽Socket上;
進入while迴圈,等待新的聯接;
如果有新的聯接,那麼建立新的socket來對應這個聯接的會話。
值得注意的就是這一句聯接程式碼:listener.Accept()。執行這一句的時候,程式就在這個地方等待,直到有新的聯檢請求的時候程式才會執行下一句。這是同步執行,當然也可以非同步執行。
新的聯接Socket建立了(Accept之後),對於這些新的socket該怎麼辦呢?他們依然是一個迴圈等待,所以依然需要建立新的Thread給這些Socket去處理會話(接收/傳送訊息),而這個Thread就要接收引數了。
Thread本身是不能接收引數的,為了讓它可以接收引數,可以採用定義新類,新增引數作為屬性的方法來解決。
因為每一個Socket是一個Connection週期,所以我定義了這麼一個類public class Connection。這個類至少有這樣一個建構函式public Connection(Socket socket); 之所以這麼做,就是為了把Socket引數傳給這個Connection物件,然後好讓Listener啟動這個Thread的時候,Thread可以知道他正在處理哪一個Socket。
具體處理的方法:(在Listener的StartListening函式,ocket connection = listener.Accept();之後)
Connection gpsCn = new Connection(connection);
//each socket will be wait for data. keep the connection.
Thread thread = new Thread(new ThreadStart(gpsCn.WaitForSendData));
thread.Name = connection.RemoteEndPoint.ToString();
thread.Start();
如此一來,這個新的socket在Accept之後就在新的Thread中運行了。
3:Connection的會話處理
建立了新的Connection(也就是socket),遠端就可以和這個socket進行會話了,無非就是send和receive。
現在先看看怎麼寫的這個執行緒執行的Connection. WaitForSendData函式
while (true)
{
bytes = new byte[1024];
string data = "";
//systm will be waiting the msg of receive envet. like Accept();
//here will be suspended while waiting for socket income msg.
int bytesRec = this._connection.Receive(bytes);
_lastConnectTime = DateTime.Now;
if (bytesRec == 0)//close envent
{
Logger.Log("Close Connection", _connection.RemoteEndPoint.ToString());
break;
}
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
//…….handle your data.
}
可以看到這個處理的基本步驟如下:
執行Receive函式,接收遠端socket傳送的資訊;
把資訊從位元組轉換到string;
處理該資訊,然後進入下一個迴圈,繼續等待socket傳送新的資訊。
值得注意的有幾個:
1:Receive函式。這個函式和Listener的Accept函式類似。在這個地方等待執行,如果沒有新的訊息,這個函式就不會執行下一句,一直等待。
2:接收的是位元組流,需要轉化成字串
3:判斷遠端關閉聯接的方式
4:如果對方的訊息非常大,還得迴圈接收這個data。
4:如何管理這些聯接(thread)
通過上邊的程式,基本上可以建立一個偵聽,並且處理聯接會話。但是如何管理這些thread呢?不然大量產生thread可是一個災難。
管理的方法比較簡單,在Listener裡面我定義了一個靜態的雜湊表(static public Hashtable Connections=new Hashtable();),儲存Connection例項和它對應的Thread例項。而connection中也加入了一個最後聯接時間的定義(private DateTime _lastConnectTime;)。在新連結建立的時候(Listener的Accept()之後)就把Connection例項和Thread例項存到雜湊表中;在Connection的Receive的時候修改最後聯接時間。這樣我們就可以知道該Connection在哪裡,並且會話是否活躍。
然後在Winform程式裡頭可以管理這些會話了,設定設定超時。

在網路環境下,我們最感興趣的兩個名稱空間是System.Net和 System.Net.Sockets。System.Net名稱空間通常與較高程的操作有關,例如download或upload,試用HTTP和其他協議進行Web請求等等,而System.Net.Sockets名稱空間所包含的類通常與較低程的操作有關。如果要直接使用Sockets或者 TCP/IP之類的協議,這個名稱空間的類是非常有用的。
  在.Net中,System.Net.Sockets 名稱空間為需要嚴密控制網路訪問的開發人員提供了 Windows Sockets (Winsock) 介面的託管實現。System.Net 名稱空間中的所有其他網路訪問類都建立在該套接字Socket實現之上,如TCPClient、TCPListener 和 UDPClient 類封裝有關建立到 Internet 的 TCP 和 UDP 連線的詳細資訊;NetworkStream類則提供用於網路訪問的基礎資料流等,常見的許多Internet服務都可以見到Socket的蹤影,如 Telnet、Http、Email、Echo等,這些服務儘管通訊協議Protocol的定義不同,但是其基礎的傳輸都是採用的Socket。
  其實,Socket可以象流Stream一樣被視為一個數據通道,這個通道架設在應用程式端(客戶端)和遠端伺服器端之間,而後,資料的讀取(接收)和寫入(傳送)均針對這個通道來進行。
  可見,在應用程式端或者伺服器端建立了Socket物件之後,就可以使用Send/SentTo方法將資料傳送到連線的Socket,或者使用Receive/ReceiveFrom方法接收來自連線Socket的資料。
  針對Socket程式設計,.NET 框架的 Socket 類是 Winsock32 API 提供的套接字服務的託管程式碼版本。其中為實現網路程式設計提供了大量的方法,大多數情況下,Socket 類方法只是將資料封送到它們的本機 Win32 副本中並處理任何必要的安全檢查。如果你熟悉Winsock API函式,那麼用Socket類編寫網路程式會非常容易,當然,如果你不曾接觸過,也不會太困難,跟隨下面的解說,你會發覺使用Socket類開發 windows 網路應用程式原來有規可尋,它們在大多數情況下遵循大致相同的步驟。
  在使用之前,你需要首先建立Socket物件的例項,這可以通過Socket類的構造方法來實現:
public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);
  其中,addressFamily 引數指定 Socket 使用的定址方案,socketType 引數指定 Socket 的型別,protocolType 引數指定 Socket 使用的協議。
  下面的示例語句建立一個 Socket,它可用於在基於 TCP/IP 的網路(如 Internet)上通訊。
Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  若要使用 UDP 而不是 TCP,需要更改協議型別,如下面的示例所示:
Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  一旦建立 Socket,在客戶端,你將可以通過Connect方法連線到指定的伺服器,並通過Send/SendTo方法向遠端伺服器傳送資料,而後可以通過 Receive/ReceiveFrom從服務端接收資料;而在伺服器端,你需要使用Bind方法繫結所指定的介面使Socket與一個本地終結點相聯,並通過Listen方法偵聽該介面上的請求,當偵聽到使用者端的連線時,呼叫Accept完成連線的操作,建立新的Socket以處理傳入的連線請求。使用完 Socket 後,記住使用 Shutdown 方法禁用 Socket,並使用 Close 方法關閉 Socket。
  可以看出,以上許多方法包含EndPoint型別的引數,在Internet中,TCP/IP 使用一個網路地址和一個服務埠號來唯一標識裝置。網路地址標識網路上的特定裝置;埠號標識要連線到的該裝置上的特定服務。網路地址和服務埠的組合稱為終結點,在 .NET 框架中正是由 EndPoint 類表示這個終結點,它提供表示網路資源或服務的抽象,用以標誌網路地址等資訊。.Net同時也為每個受支援的地址族定義了 EndPoint 的子代;對於 IP 地址族,該類為 IPEndPoint。IPEndPoint 類包含應用程式連線到主機上的服務所需的主機和埠資訊,通過組合服務的主機IP地址和埠號,IPEndPoint 類形成到服務的連線點。
  用到IPEndPoint類的時候就不可避免地涉及到計算機IP地址,System.Net名稱空間中有兩種類可以得到IP地址例項:
  IPAddress類:IPAddress 類包含計算機在 IP 網路上的地址。其Parse方法可將 IP 地址字串轉換為 IPAddress 例項。下面的語句建立一個 IPAddress 例項:
IPAddress myIP = IPAddress.Parse("192.168.0.1");
  Dns 類:向使用 TCP/IP Internet 服務的應用程式提供域名服務。其Resolve 方法查詢 DNS 伺服器以將使用者友好的域名(如"host.mydomain.com")對映到數字形式的 Internet 地址(如 192.168.0.1)。Resolve方法 返回一個 IPHostEnty 例項,該例項包含所請求名稱的地址和別名的列表。大多數情況下,可以使用 AddressList 陣列中返回的第一個地址。下面的程式碼獲取一個 IPAddress 例項,該例項包含伺服器 host.mydomain.com 的 IP 地址。
IPHostEntry ipHostInfo = Dns.Resolve("host.mydomain.com ");
IPAddress ipAddress = ipHostInfo.AddressList[0];
  你也可以使用GetHostName方法得到IPHostEntry例項:
IPHosntEntry hostInfo=Dns.GetHostByName("host.mydomain.com ")
  在使用以上方法時,你將可能需要處理以下幾種異常:
  SocketException異常:訪問Socket時作業系統發生錯誤引發
  ArgumentNullException異常:引數為空引用引發
  ObjectDisposedException異常:Socket已經關閉引發
  在掌握上面得知識後,下面的程式碼將該伺服器主機( host.mydomain.com的 IP 地址與埠號組合,以便為連線建立遠端終結點:
IPEndPoint ipe = new IPEndPoint(ipAddress,11000);
  確定了遠端裝置的地址並選擇了用於連線的埠後,應用程式可以嘗試建立與遠端裝置的連線。下面的示例使用現有的 IPEndPoint 例項與遠端裝置連線,並捕獲可能引發的異常:
try
{
temp.Connect(ipe);//嘗試連線
}
//處理引數為空引用異常
catch(ArgumentNullException ae)
{
Console.WriteLine("ArgumentNullException : {0}", ae.ToString());
}
//處理作業系統異常
catch(SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
  需要知道的是:Socket 類支援兩種基本模式:同步和非同步。其區別在於:在同步模式中,對執行網路操作的函式(如 Send 和 Receive)的呼叫一直等到操作完成後才將控制返回給呼叫程式。在非同步模式中,這些呼叫立即返回。
綜合運用以上闡述的使用Visual C#進行Socket網路程式開發的知識,下面的程式是一個簡單的Socket通訊例項,client向server傳送一段測試字串,server接收並顯示出來,給予client成功相應。
//client端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace socketsample
{
 class Class1
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    c.Connect(ipe);
    string sendStr = "hello!This is a socket test";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    c.Send(bs, bs.Length, 0);
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = c.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    c.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}
//server端
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Project1
{
 class Class2
 {
  static void Main()
  {
   try
   {
    int port = 2000;
    string host = "127.0.0.1";
    IPAddress ip = IPAddress.Parse(host);
    IPEndPoint ipe = new IPEndPoint(ip, port);
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    s.Bind(ipe);
    s.Listen(0);
    Socket temp = s.Accept();
    string recvStr = "";
    byte[] recvBytes = new byte[1024];
    int bytes;
    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
    Console.WriteLine(recvStr);
    string sendStr = "Ok!Sucess!";
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);
    temp.Send(bs, bs.Length, 0);
    temp.Shutdown(SocketShutdown.Both);
    temp.Close();
    s.Shutdown(SocketShutdown.Both);
    s.Close();
   }
   catch (ArgumentNullException e)
   {
    Console.WriteLine("ArgumentNullException: {0}", e);
   }
   catch (SocketException e)
   {
    Console.WriteLine("SocketException: {0}", e);
   }
   Console.ReadLine();
  }
 }
}
  以上程式在VS Express 2005 .Net2.0環境下測試通過。

C#UDP的多路廣播組的傳送和接收
下列範例使用 UdpClient,在通訊埠11000傳送UDP 資料包至多點傳送位址群組 224.268.100.2。它傳送命令列上指定的資訊字串。
C# code
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UDPMulticastSender {
private static IPAddress GroupAddress =
IPAddress.Parse("224.168.100.2");
private static int GroupPort = 11000;
private static void Send( String message) {
UdpClient sender = new UdpClient();
IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);
try {
Console.WriteLine("Sending datagram : {0}", message);
byte[] bytes = Encoding.ASCII.GetBytes(message);
sender.Send(bytes, bytes.Length, groupEP);
sender.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args) {
Send(args[0]);
return 0;
}
}

下列範例使用 UdpClient,在通訊埠 11000 監聽廣播到多點傳送位址群組 224.168.100.2 的 UDP 資料包。它接收資訊字串,並將資訊寫入主控臺 (Console)。

C# code

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

public class UDPMulticastListener {

private static readonly IPAddress GroupAddress =

IPAddress.Parse("224.168.100.2");

private const int GroupPort = 11000;

private static void StartListener() {

bool done = false;

UdpClient listener = new UdpClient();

IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);

try {

listener.JoinMulticastGroup(GroupAddress);

listener.Connect(groupEP);

while (!done) {

Console.WriteLine("Waiting for broadcast");

byte[] bytes = listener.Receive( ref groupEP);

Console.WriteLine("Received broadcast from {0} :\n {1}\n",

groupEP.ToString(),

Encoding.ASCII.GetString(bytes,0,bytes.Length));

}

listener.Close();

} catch (Exception e) {

Console.WriteLine(e.ToString());

}

}

public static int Main(String[] args) {

StartListener();

return 0;

}

}

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

public class UDPMulticastSender {

private static IPAddress GroupAddress =

IPAddress.Parse("224.168.100.2");

private static int GroupPort = 11000;

private static void Send( String message) {

UdpClient sender = new UdpClient();

IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);

try {

Console.WriteLine("Sending datagram : {0}", message);

byte[] bytes = Encoding.ASCII.GetBytes(message);

sender.Send(bytes, bytes.Length, groupEP);

sender.Close();

} catch (Exception e) {

Console.WriteLine(e.ToString());

}

}

public static int Main(String[] args) {

Send(args[0]);

return 0;

}

}

C# code

try

{

UdpClient udp=new UdpClient(new IPEndPoint(ipAddress,startPort+i));

udp.Close();

unUsedPort=startPort+i;

break;

}

catch

{

}

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Collections;

using System.Collections.Specialized;

using System.Threading;

using System.Net.Sockets;

using System.Net;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.IO;

namespace 聊天工具伺服器

{

public partial class FormMain : Form

{

public FormMain()

{

InitializeComponent();

}

#region 欄位定義

/// <summary>

/// 伺服器程式使用的埠,預設為8888

/// </summary>

private int _port = 8888;

/// <summary>

/// 接收資料緩衝區大小2K

/// </summary>

private const int _maxPacket =2 * 1024;

/// <summary>

/// 伺服器端的監聽器

/// </summary>

private TcpListener _tcpl = null;

Thread _receiveThread;

/// <summary>

/// 儲存所有客戶端會話的雜湊表

/// </summary>

private Hashtable _transmit_tb = new Hashtable();

/// <summary>

/// 當前檔案路徑

/// </summary>

string MyPath = null;

/// <summary>

/// 使用者基本資訊表,包括UserName,UserPwd,UserNich,UserImg,ZX,UserIp

/// </summary>

DataTable TabUser = new DataTable();

/// <summary>

/// 使用者訊息表,儲存使用者不線上時的訊息

/// </summary>

DataTable TabUserMessage = new DataTable();

#endregion

/// <summary>

/// 序列化線上列表,向客戶端返回序列化後的位元組陣列

/// </summary>

/// <returns>序列化後的位元組陣列 </returns>

private byte[] SerializeOnlineList()

{

StringCollection onlineList = new StringCollection();

foreach (object o in _transmit_tb.Keys)

{

onlineList.Add(o as string);

}

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, onlineList);

byte[] ret = stream.ToArray();

stream.Close();

return ret;

}

/// <summary>

/// 序列化好友列表,向客戶端返回序列化後的datatable

/// </summary>

/// <returns>序列化後的位元組陣列 </returns>

private bool SerializeFriendList(object obj, Socket clientSkt)

{

DataTable TabmyFriend = new DataTable();

TabmyFriend.TableName = obj as string;

try {

TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + TabmyFriend.TableName + ".xml");

TabmyFriend.Columns.Add("UserImg", typeof(String));

TabmyFriend.Columns.Add("UserNich", typeof(String));

TabmyFriend.Columns.Add("ZX", typeof(Boolean));

TabmyFriend.Columns.Add("UserIp", typeof(String));

foreach (DataRow myrow in TabmyFriend.Rows)

{

DataRow[] DataRows = TabUser.Select(" UserName = '" + myrow["UserName"].ToString() + "'");

if (DataRows.Length > 0)

{

myrow["UserImg"] = DataRows[0]["UserImg"].ToString();

myrow["UserNich"] = DataRows[0]["UserNich"].ToString();

try

{

myrow["ZX"] = (bool)DataRows[0]["ZX"];

myrow["UserIp"] = DataRows[0]["UserIp"].ToString();

}

catch

{

myrow["ZX"] = false;

myrow["UserIp"] = "";

}

}

}

}

catch

{

TabmyFriend.Columns.Add("UserName", typeof(String));

TabmyFriend.Columns.Add("UserImg", typeof(String));

TabmyFriend.Columns.Add("ZX", typeof(Boolean));

TabmyFriend.Columns.Add("UserIp", typeof(String));

}

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, TabmyFriend);

stream.Position = 0;

byte[] ret = new byte[_maxPacket];

int count = 0;

count = stream.Read(ret, 0, _maxPacket);

//先發送響應訊號,使用者客戶機的判斷

clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestFriendList"));

while (count >0)

{

clientSkt.Send(ret);

count = stream.Read(ret, 0, _maxPacket);

}

//傳送結束訊號

clientSkt.Send(Encoding.Unicode.GetBytes("Find::RequestFriendListEnd"));

stream.Close();

return true ;

}

private void FormMain_Load(object sender, EventArgs e)

{

MyPath = Application.StartupPath;

Read_User();

ReadTabUserMessage();

_receiveThread = new Thread(new ThreadStart(StartUp));

_receiveThread.Start();

}

/// <summary>

/// 讀取所有使用者資訊

/// </summary>

private void Read_User()

{

try

{

TabUser.ReadXml(MyPath + "\\User.xml");

}

catch

{

TabUser.TableName = "User";

TabUser.Columns.Add("UserName", typeof(String));

TabUser.Columns.Add("UserPwd", typeof(String));

TabUser.Columns.Add("UserNich", typeof(String));

TabUser.Columns.Add("UserImg", typeof(String));

}

TabUser.Columns.Add("ZX", typeof(Boolean));

TabUser.Columns.Add("UserIp", typeof(String));

}

/// <summary>

/// 新使用者上/下線後,更新其好友的(好友列表)

/// </summary>

/// <param name="UserName"> </param>

/// <param name="OnLine"> </param>

/// <param name="IpAddress"> </param>

private void UpdateFriendList(string UserName, bool OnLine, string IpAddress)

{

DataTable TabmyFriend = new DataTable();

TabmyFriend.TableName = UserName;

string svrlog = null;

string []UserInformation = new string[2];//UserName + "$" + IpAddress;

UserInformation[0] = UserName;

UserInformation[1] = IpAddress;

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, UserInformation);

byte[] ret = stream.ToArray();

stream.Close();

if (OnLine)

{

svrlog = "cmd::RequestAddFriendList";

}

else

{

svrlog = "cmd::RequestRemoveFriendList";

DataRow[] DataRows = TabUser.Select(" UserName = '" + UserName + "'");

if (DataRows.Length > 0)

{

DataRows[0]["ZX"] = false;

DataRows[0]["UserIp"] = "";

}

}

try

{

TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + TabmyFriend.TableName + ".xml");

foreach (DataRow myrow in TabmyFriend.Rows)

{

if(_transmit_tb.ContainsKey(myrow["UserName"].ToString()))

{

Socket _clientSkt = _transmit_tb[myrow["UserName"].ToString()] as Socket;

_clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));

_clientSkt.Send(ret);

}

}

}

catch

{ }

}

[code=C#][/code /// <summary>

/// 執行緒執行體,轉發訊息

/// </summary>

/// <param name="obj">傳遞給執行緒執行體的使用者名稱,用以與使用者通訊 </param>

private void ThreadFunc(object obj)

{

//通過轉發表得到當前使用者套接字

Socket clientSkt = _transmit_tb[obj] as Socket;

//主迴圈

while (true)

{

try

{

//接受第一個資料包。

//由於程式邏輯結構簡單,所以在這裡對客戶機發送的第一個包內容作逐一判斷,

//這裡的實現不夠優雅,但不失為此簡單模型的一個解決之道。

byte[] packetBuff = new byte[_maxPacket];

clientSkt.Receive(packetBuff);

string _str = Encoding.Unicode.GetString(packetBuff).TrimEnd('\0');

//如果是發給不線上好友的資訊

if (_str.StartsWith("cmd::FriendMessage"))

{

string UserName = _str.Substring("cmd::FriendMessage".Length, 20).Trim();

string MessageS = _str.Substring("cmd::FriendMessage".Length + 20, _str.Length - "cmd::FriendMessage".Length - 20);

SaveMessage(obj as string, UserName, MessageS);

continue;

}

//如果是離線請求

if (_str.StartsWith("cmd::RequestLogout"))

{

_transmit_tb.Remove(obj);

UpdateFriendList((string)obj, false, "");

// string svrlog = string.Format("[系統訊息]使用者 {0} 在 {1} 已斷開... 當前線上人數: {2}\r\n\r\n", obj, DateTime.Now, _transmit_tb.Count);

// Console.WriteLine(svrlog);

//向所有客戶機發送系統訊息

//foreach (DictionaryEntry de in _transmit_tb)

//{

// string _clientName = de.Key as string;

// Socket _clientSkt = de.Value as Socket;

// _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));

//}

Thread.CurrentThread.Abort();

}

//如果是請求好友列表

if (_str.StartsWith("cmd::RequestFriendList"))

{

SerializeFriendList(obj, clientSkt);

// 將該使用者不線上時的資訊傳送給使用者

DataTable TabMessage = ReadMessage(obj as string);

if (TabMessage != null)

{

foreach (DataRow myrow in TabMessage.Rows)

{

if (myrow["SendUserName"].ToString() == "System::Message")

{

clientSkt.Send(Encoding.Unicode.GetBytes(myrow["Message"].ToString()));

}

else

{

clientSkt.Send(Encoding.Unicode.GetBytes("cmd::FriendMessage" + myrow["SendUserName"].ToString().PadRight(20, ' ') + myrow["Message"].ToString()));

}

}

}

//這裡不需要再繼續接受後繼資料包了,跳出當前迴圈體。

continue;

}

////如果是請求好友列表

//if (_str.StartsWith("cmd::RequestOnLineList"))

//{

// byte[] onlineBuff = SerializeOnlineList();

// //先發送響應訊號,使用者客戶機的判斷

// clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestOnLineList"));

// clientSkt.Send(onlineBuff);

// //這裡不需要再繼續接受後繼資料包了,跳出當前迴圈體。

// continue;

//}

//查詢使用者

if (_str.StartsWith("Find::FindFriend"))

{

DataTable TabFind = TabUser.Clone();

DataRow [] FindRow =null ;

string UserName = _str.Substring("Find::FindFriend".Length, _str.Length - "Find::FindFriend".Length);

if (UserName.Equals("Find::WhoOnLine"))

{ //看誰線上

FindRow = TabUser.Select(" ZX = 1");

}

else//精確查詢

{

FindRow = TabUser.Select("UserName = '" + UserName + "'");

}

foreach (DataRow myrow in FindRow)

{

TabFind.ImportRow(myrow);

}

clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriend"));

IFormatter format = new BinaryFormatter();

MemoryStream stream = new MemoryStream();

format.Serialize(stream, TabFind);

stream.Position = 0;

byte[] ret = new byte[_maxPacket];

int count = 0;

count = stream.Read(ret, 0, _maxPacket);

while (count >0)

{

clientSkt.Send(ret);

count = stream.Read(ret, 0, _maxPacket);

}

clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriendEnd"));

stream.Close();

TabFind = null;

FindRow = null;

//這裡不需要再繼續接受後繼資料包了,跳出當前迴圈體。

continue;

}

//請求新增好友

if (_str.StartsWith("Find::AddFriendAsk"))

{

string UserName = _str.Substring("Find::AddFriendAsk".Length, _str.Length - "Find::AddFriendAsk".Length);

//通過轉發表查詢接收方的套接字

if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserName))

{

Socket receiverSkt = _transmit_tb[UserName] as Socket;

receiverSkt.Send(Encoding.Unicode.GetBytes("Find::AddFriendAsk" + obj as string));

}

//這裡不需要再繼續接受後繼資料包了,跳出當前迴圈體。

continue;

}

//回覆答應新增好友

if (_str.StartsWith("Find::AddFriendYes"))

{

string UserName = _str.Substring("Find::AddFriendYes".Length, _str.Length - "Find::AddFriendYes".Length);

//// 儲存資料

DataTable TabmyFriend = new DataTable() ;

//儲存該使用者

TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + obj as string + ".xml");

DataRow newRow = TabmyFriend.NewRow();

newRow["UserName"] = UserName;

TabmyFriend.Rows.Add(newRow);

TabmyFriend.WriteXml(MyPath + "\\UserFriend\\" + obj as string + ".xml", XmlWriteMode.WriteSchema, false);

//儲存其好友

TabmyFriend = new DataTable();

TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + UserName + ".xml");

DataRow newRow1 = TabmyFriend.NewRow();

newRow1["UserName"] = obj as string;

TabmyFriend.Rows.Add(newRow1);

TabmyFriend.WriteXml(MyPath + "\\UserFriend\\" + UserName + ".xml", XmlWriteMode.WriteSchema, false);

TabmyFriend = null;

//更新好友列表

SerializeFriendList(obj, clientSkt);

上面發了伺服器端,沒發客戶端,現在補上!不知道寫的好不好,見笑了

C# code

public partial class Form1 : Form

{

private TcpClient client;

private bool isExit = false;

private NetworkStream networkStream;

private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);

#region 用於一個執行緒操作另一個執行緒的控制元件

private delegate void SetListBoxCallback(string str);

private SetListBoxCallback setListBoxCallBack;

private delegate void SetRichTextBoxCallback(string str);

private SetRichTextBoxCallback setRichTextBoxCallBack;

#endregion

public Form1()

{

InitializeComponent();

listBoxStatus.HorizontalScrollbar = true;

setListBoxCallBack = new SetListBoxCallback(SetListBox);

setRichTextBoxCallBack = new SetRichTextBoxCallback(SetReceiveText);

}

//狀態顯示

private void SetListBox(string str)

{

listBoxStatus.Items.Add(str);

listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1;

listBoxStatus.ClearSelected();

}

//接收客戶端資訊

private void SetReceiveText(string str)

{

richTextBoxReceive.AppendText(str);

}

//連線伺服器....

private void buttonConnet_Click(object sender, EventArgs e)

{

client = new TcpClient(AddressFamily.InterNetwork);

//得到伺服器IP

IPAddress ip= IPAddress.Parse("127.0.0.1");

//建立一個委託,並知名在非同步操作完成時執行的方法

AsyncCallback callback = new AsyncCallback(RequestCallBack);

allDone.Reset();

client.BeginConnect(ip, 7100, RequestCallBack, client);

}

private void RequestCallBack(IAsyncResult ar)

{

allDone.Set();

try

{

client = (TcpClient)ar.AsyncState;

client.EndConnect(ar);

listBoxStatus.Invoke(setListBoxCallBack, string.Format("與伺服器{0}連線成功", client.Client.RemoteEndPoint));

networkStream = client.GetStream();

ReadObject readObject = new ReadObject(networkStream, client.ReceiveBufferSize);

networkStream.BeginRead(readObject.bytes, 0, readObject.bytes.Length, ReadCallBack, readObject);

}

catch (Exception e1)

{

listBoxStatus.Invoke(setListBoxCallBack, e1.Message);

return;

}

}

//非同步操作完成時執行的回撥呼叫的方法

private void ReadCallBack(IAsyncResult ar)

{

try

{

ReadObject ro = (ReadObject)ar.AsyncState;

int count = ro.netStream.EndRead(ar);

richTextBoxReceive.Invoke(setRichTextBoxCallBack, System.Text.Encoding.UTF8.GetString(ro.bytes, 0, count));

if (isExit == false)

{

ro = new ReadObject(networkStream, client.ReceiveBufferSize);

networkStream.BeginRead(ro.bytes, 0, ro.bytes.Length, ReadCallBack, ro);

}

}

catch (Exception e2)

{

listBoxStatus.Invoke(setListBoxCallBack, e2.Message);

return;

}

}

//傳送資料

private void SendString(string str)

{

try

{

byte[] by = System.Text.Encoding.UTF8.GetBytes(str+"\r\n");

networkStream.BeginWrite(by, 0, by.Length, new AsyncCallback(SendCallBack), networkStream);

networkStream.Flush();

}catch(Exception e3){

listBoxStatus.Invoke(setListBoxCallBack, e3.Message);

return;

}

}

//傳送資料回撥的方法

private void SendCallBack(IAsyncResult ar)

{

try

{

networkStream.EndWrite(ar);

}

catch (Exception e4)

{

listBoxStatus.Invoke(setListBoxCallBack, e4.Message);

return;

}

}

private void buttonSend_Click(object sender, EventArgs e)

{

SendString(richTextBoxSend.Text);

richTextBoxSend.Clear();

}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)

{

isExit = true;

allDone.Set();

}

}

相關推薦

C#完整通訊程式碼同步非同步UDPTCP)

C# code namespace UDPServer { class Program { static void Main(string[] args) { int recv; byte[] data = new byte[1024]; //構建TCP 伺服器 //得到本機IP,設定TCP埠號 IPEnd

C#Socket通訊基礎非同步Socket通訊TCP)伺服器與客戶端

一、效果圖 二、伺服器端程式碼(原始碼下載地址:https://download.csdn.net/download/xiaochenxihua/10748789) using System; using System.Collections.Generic; using System

C#Socket通訊基礎非同步Socket通訊UDP

一、通訊原理參考https://blog.csdn.net/xiaochenXIHUA/article/details/83446031。 非同步通訊解決同步通訊的缺點可以雙向傳送和接收資訊;非同步通訊思路是引入多執行緒機制,在一個程序中使用兩個執行緒,分別處理接收執行緒與傳送執行緒,這種機制稱

C#Socket通訊基礎同步Socket通訊UDP

一、UDP通訊原理 UDP協議使用無連線的套接字,因此不需要再網路裝置之間傳送連線資訊,但是必須用Bind方法繫結到一個本地地址/埠上。 ①建立套接字 ②繫結IP地址和埠作為伺服器端 ③直接使用SendTo/ReceiveFrom來執行操作 注意:同步Socket(UDP)通訊存

C語言和cuda C實現的程式碼教科書上的格式)

一般教科書都這麼寫,感覺不如STL的好。記下以便查閱。 #include <cuda_runtime.h> #include <iostream> #include <stdio.h> __global__ void vector_add_gpu_2(fl

C#Socket通訊原理基礎篇)

這幾天博主花了4天時間去學習,整理Socket通訊。大致懂了一點,現在我來總結一下關於C#Socket通訊的原理首先我們要知道網路中的程序是如何進行通訊的在本地可以通過程序PID來唯一標識一個程序,但是在網路中這是行不通的。其實TCP/IP協議族已經幫我們解決了這個問題,網路

C語言經典程式碼1-8)

古典問題:有一對兔子,從出生後第3個月起每個月都生一對兔子,小兔子長到第三個月後每個月又生一對兔子,假如兔子都不死,問每個月的兔子總數為多少? 兔子的規律為數列1,1,2,3,5,8,13,21…. /*古典問題:有一對兔子,從出生後第3個月起每個月都生一對

C語言經典程式碼判斷完全平方數)

題目:一個整數,它加上100後是一個完全平方數,再加上168又是一個完全平方數,請問該數是多少?  1.程式分析:在10萬以內判斷,先將該數加上100後再開方,再將該數加上268後再開方,如果開方後 

C/C++網路通訊程式設計一)

一、Internet與TCP/IP協議     Internet的發展大致可為四個階段:60年代,Internet起源;70年代,TCP/IP協議,Internet隨之發展起來;80年代,NFSnet出現,併成為當今Internet的基礎;90年代,Internet進入高速

C++Socket通訊總結C++實現)

一、Socket是什麼    Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓Socket去組織資

分享個C++封裝Libcurl程式碼支援下載檔案、GET\POST、重定向斷點續傳等功能)

前言 前面分享過一個Windows上封裝Winhttp和WinInet API的程式碼,結果下載頁好評特別多(呵呵),謝謝大家賞臉。文章地址:開源一個C++實現的簡單HTTP協議處理庫,裡面有程式碼資源下載地址。但是,在實際開發過程中我發現WinHttp API嚴重依賴微

C++ Socket通訊總結C++實現)

  因為專案需要,服務端需要一個SOCKET來接收客戶端的請求,好吧,沒辦法度娘哇,結果很多都是linux的例子,功夫不負有心人啊,終於找到個demo,並且客戶端程式碼詳盡,記錄之,以便以後檢視。 一、Socket是什麼    Socket是應用層與TCP/IP協議族

同一個物件繫結個響應事件並都執行和此例子的相容程式碼

要點: 1.因為 onclick=" "  新增的元素響應事件,先新增的事件,會被後來新增的事件層疊掉,只能執行最後一個響應的事件 所以要用到事件監聽addElementLitener()來繫結多個處理函式,而因為相容性的問題需要相容程式碼。 2.在IE8中,addE

一個dom,選事件觸發兩個事件是同步還是非同步

問題產生原因: 使用者充值介面,一個選擇支付方式的dom綁定了一個插入訂單的 ajax。 為了監測使用者點了哪個支付方式,現在要把選擇哪個支付方式記錄下來。 當然可以在這個ajax請求的方法裡面加入一個插入監測資料。但是考慮到插入訂單的

MySQL主從MySQL proxy Lua讀寫分離設置一主同步配置分庫分表方案)

否則 count user username 2個 ons 基礎 zxvf 路徑 Mysql Proxy Lua讀寫分離設置一.讀寫分離說明讀寫分離(Read/Write Splitting),基本的原理是讓主數據庫處理事務性增、改、刪操作(INSERT、UPDATE、DE

PAT 1007 素數猜想 C++解決最後一測試超時)

讓我們定義d​n​​為:d​n​​=p​n+1​​−p​n​​,其中p​i​​是第i個素數。顯然有d​1​​=1,且對於n>1有d​n​​是偶數。“素數對猜想”認為“存在無窮多對相鄰且差為2的素數”。 現給定任意正整數N(<10​5​​),請計算不超過N的滿足猜

C++找出一個二維陣列中的鞍即該位置上的元素在該行上最大在該列上最小也可能沒有鞍

今日正式用csdn部落格記錄,回顧我所學到的知識,分享一些我的人生感悟和自身經歷。也希望未來通夠過此平臺和更多喜愛程式設計的人交流學習。 道聽途說再加上自己的感悟,認為程式設計最重要的是思想,而不是語言本身,語言只是個工具。所以我們得先學思想。遇到問題,應該先想如果是自己去做會怎麼處理,但我們不

6-3 使用函式驗證哥德巴赫猜想 10 分)c語言解答附上我覺得注意

6-3 使用函式驗證哥德巴赫猜想 (10 分) 本題要求實現一個判斷素數的簡單函式,並利用該函式驗證哥德巴赫猜想:任何一個不小於6的偶數均可表示為兩個奇素數之和。素數就是隻能被1和自身整除的正整數。注意:1不是素數,2是素數。 函式介面定義: int prime( int p ); vo

vue元件通訊選傳值動態傳值父傳子子傳父)

vue說到元件通訊,無非是父元件傳子元件,子元件傳父元件,跨級元件傳值,同級元件傳值,個人覺得,除了父子元件的傳值,其餘情況就可以用vuex來解決了,這篇先不說vuex,這裡介紹父子元件傳值。不會你打我! 一、父元件傳子元件,核心--props 下面是場景,點選傳值給子元