基于C#的socket編程的TCP異步的實(shí)現(xiàn)代碼
一、摘要
本篇闡述基于TCP通信協(xié)議的異步實(shí)現(xiàn)。
二、實(shí)驗(yàn)平臺(tái)
Visual Studio 2010
三、異步通信實(shí)現(xiàn)原理及常用方法
3.1 建立連接
在同步模式中,在服務(wù)器上使用Accept方法接入連接請(qǐng)求,而在客戶(hù)端則使用Connect方法來(lái)連接服務(wù)器。相對(duì)地,在異步模式下,服務(wù)器可以使用BeginAccept方法和EndAccept方法來(lái)完成連接到客戶(hù)端的任務(wù),在客戶(hù)端則通過(guò)BeginConnect方法和EndConnect方法來(lái)實(shí)現(xiàn)與服務(wù)器的連接。
BeginAccept在異步方式下傳入的連接嘗試,它允許其他動(dòng)作而不必等待連接建立才繼續(xù)執(zhí)行后面程序。在調(diào)用BeginAccept之前,必須使用Listen方法來(lái)偵聽(tīng)是否有連接請(qǐng)求,BeginAccept的函數(shù)原型為:
BeginAccept(AsyncCallback AsyncCallback, Ojbect state)
參數(shù):
AsyncCallBack:代表回調(diào)函數(shù)
state:表示狀態(tài)信息,必須保證state中包含socket的句柄
使用BeginAccept的基本流程是:
(1)創(chuàng)建本地終節(jié)點(diǎn),并新建套接字與本地終節(jié)點(diǎn)進(jìn)行綁定;
(2)在端口上偵聽(tīng)是否有新的連接請(qǐng)求;
(3)請(qǐng)求開(kāi)始接入新的連接,傳入Socket的實(shí)例或者StateOjbect的實(shí)例。
參考代碼:
//定義IP地址
IPAddress local = IPAddress.Parse("127.0,0,1");
IPEndPoint iep = new IPEndPoint(local,13000);
//創(chuàng)建服務(wù)器的socket對(duì)象
Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
server.Bind(iep);
server.Listen(20);
server.BeginAccecpt(new AsyncCallback(Accept),server);
當(dāng)BeginAccept()方法調(diào)用結(jié)束后,一旦新的連接發(fā)生,將調(diào)用回調(diào)函數(shù),而該回調(diào)函數(shù)必須包括用來(lái)結(jié)束接入連接操作的EndAccept()方法。
該方法參數(shù)列表為 Socket EndAccept(IAsyncResult iar)
下面為回調(diào)函數(shù)的實(shí)例:
void Accept(IAsyncResult iar)
{
//還原傳入的原始套接字
Socket MyServer = (Socket)iar.AsyncState;
//在原始套接字上調(diào)用EndAccept方法,返回新的套接字
Socket service = MyServer.EndAccept(iar);
}
至此,服務(wù)器端已經(jīng)準(zhǔn)備好了??蛻?hù)端應(yīng)通過(guò)BeginConnect方法和EndConnect來(lái)遠(yuǎn)程連接主機(jī)。在調(diào)用BeginConnect方法時(shí)必須注冊(cè)相應(yīng)的回調(diào)函數(shù)并且至少傳遞一個(gè)Socket的實(shí)例給state參數(shù),以保證EndConnect方法中能使用原始的套接字。下面是一段是BeginConnect的調(diào)用:
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp)
IPAddress ip=IPAddress.Parse("127.0.0.1");
IPEndPoint iep=new IPEndPoint(ip,13000);
socket.BeginConnect(iep, new AsyncCallback(Connect),socket);
EndConnect是一種阻塞方法,用于完成BeginConnect方法的異步連接誒遠(yuǎn)程主機(jī)的請(qǐng)求。在注冊(cè)了回調(diào)函數(shù)后必須接收BeginConnect方法返回的IASynccReuslt作為參數(shù)。下面為代碼演示:
void Connect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
除了采用上述方法建立連接之后,也可以采用TcpListener類(lèi)里面的方法進(jìn)行連接建立。下面是服務(wù)器端對(duì)關(guān)于TcpListener類(lèi)使用BeginAccetpTcpClient方法處理一個(gè)傳入的連接嘗試。以下是使用BeginAccetpTcpClient方法和EndAccetpTcpClient方法的代碼:
public static void DoBeginAccept(TcpListener listner)
{
//開(kāi)始從客戶(hù)端監(jiān)聽(tīng)連接
Console.WriteLine("Waitting for a connection");
//接收連接
//開(kāi)始準(zhǔn)備接入新的連接,一旦有新連接嘗試則調(diào)用回調(diào)函數(shù)DoAcceptTcpCliet
listner.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpCliet), listner);
}
//處理客戶(hù)端的連接
public static void DoAcceptTcpCliet(IAsyncResult iar)
{
//還原原始的TcpListner對(duì)象
TcpListener listener = (TcpListener)iar.AsyncState;
//完成連接的動(dòng)作,并返回新的TcpClient
TcpClient client = listener.EndAcceptTcpClient(iar);
Console.WriteLine("連接成功");
}
代碼的處理邏輯為:
(1)調(diào)用BeginAccetpTcpClient方法開(kāi)開(kāi)始連接新的連接,當(dāng)連接視圖發(fā)生時(shí),回調(diào)函數(shù)被調(diào)用以完成連接操作;
(2)上面DoAcceptTcpCliet方法通過(guò)AsyncState屬性獲得由BeginAcceptTcpClient傳入的listner實(shí)例;
(3)在得到listener對(duì)象后,用它調(diào)用EndAcceptTcpClient方法,該方法返回新的包含客戶(hù)端信息的TcpClient。
BeginConnect方法和EndConnect方法可用于客戶(hù)端嘗試建立與服務(wù)端的連接,這里和第一種方法并無(wú)區(qū)別。下面看實(shí)例:
public void doBeginConnect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
//開(kāi)始與遠(yuǎn)程主機(jī)進(jìn)行連接
client.BeginConnect(serverIP[0],13000,requestCallBack,client);
Console.WriteLine("開(kāi)始與服務(wù)器進(jìn)行連接");
}
private void requestCallBack(IAsyncResult iar)
{
try
{
//還原原始的TcpClient對(duì)象
TcpClient client=(TcpClient)iar.AsyncState;
//
client.EndConnect(iar);
Console.WriteLine("與服務(wù)器{0}連接成功",client.Client.RemoteEndPoint);
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
以上是建立連接的兩種方法??筛鶕?jù)需要選擇使用。
3.2 發(fā)送與接受數(shù)據(jù)
在建立了套接字的連接后,就可以服務(wù)器端和客戶(hù)端之間進(jìn)行數(shù)據(jù)通信了。異步套接字用BeginSend和EndSend方法來(lái)負(fù)責(zé)數(shù)據(jù)的發(fā)送。注意在調(diào)用BeginSend方法前要確保雙方都已經(jīng)建立連接,否則會(huì)出異常。下面演示代碼:
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
接收數(shù)據(jù)是通過(guò)BeginReceive和EndReceive方法:
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
上述代碼的處理邏輯為:
(1)首先處理連接的回調(diào)函數(shù)里得到的通訊套接字client,接著開(kāi)始接收數(shù)據(jù);
(2)當(dāng)數(shù)據(jù)發(fā)送到緩沖區(qū)中,BeginReceive方法試圖從buffer數(shù)組中讀取長(zhǎng)度為buffer.length的數(shù)據(jù)塊,并返回接收到的數(shù)據(jù)量bytesRead。最后接收并打印數(shù)據(jù)。
除了上述方法外,還可以使用基于NetworkStream相關(guān)的異步發(fā)送和接收方法,下面是基于NetworkStream相關(guān)的異步發(fā)送和接收方法的使用介紹。
NetworkStream使用BeginRead和EndRead方法進(jìn)行讀操作,使用BeginWreite和EndWrete方法進(jìn)行寫(xiě)操作,下面看實(shí)例:
static void DataHandle(TcpClient client)
{
TcpClient tcpClient = client;
//使用TcpClient的GetStream方法獲取網(wǎng)絡(luò)流
NetworkStream ns = tcpClient.GetStream();
//檢查網(wǎng)絡(luò)流是否可讀
if(ns.CanRead)
{
//定義緩沖區(qū)
byte[] read = new byte[1024];
ns.BeginRead(read,0,read.Length,new AsyncCallback(myReadCallBack),ns);
}
else
{
Console.WriteLine("無(wú)法從網(wǎng)絡(luò)中讀取流數(shù)據(jù)");
}
}
public static void myReadCallBack(IAsyncResult iar)
{
NetworkStream ns = (NetworkStream)iar.AsyncState;
byte[] read = new byte[1024];
String data = "";
int recv;
recv = ns.EndRead(iar);
data = String.Concat(data, Encoding.ASCII.GetString(read, 0, recv));
//接收到的消息長(zhǎng)度可能大于緩沖區(qū)總大小,反復(fù)循環(huán)直到讀完為止
while (ns.DataAvailable)
{
ns.BeginRead(read, 0, read.Length, new AsyncCallback(myReadCallBack), ns);
}
//打印
Console.WriteLine("您收到的信息是" + data);
}
3.3 程序阻塞與異步中的同步問(wèn)題
.Net里提供了EventWaitHandle類(lèi)來(lái)表示一個(gè)線程的同步事件。EventWaitHandle即事件等待句柄,他允許線程通過(guò)操作系統(tǒng)互發(fā)信號(hào)和等待彼此的信號(hào)來(lái)達(dá)到線程同步的目的。這個(gè)類(lèi)有2個(gè)子類(lèi),分別為AutoRestEevnt(自動(dòng)重置)和ManualRestEvent(手動(dòng)重置)。下面是線程同步的幾個(gè)方法:
(1)Rset方法:將事件狀態(tài)設(shè)為非終止?fàn)顟B(tài),導(dǎo)致線程阻塞。這里的線程阻塞是指允許其他需要等待的線程進(jìn)行阻塞即讓含WaitOne()方法的線程阻塞;
(2)Set方法:將事件狀態(tài)設(shè)為終止?fàn)顟B(tài),允許一個(gè)或多個(gè)等待線程繼續(xù)。該方法發(fā)送一個(gè)信號(hào)給操作系統(tǒng),讓處于等待的某個(gè)線程從阻塞狀態(tài)轉(zhuǎn)換為繼續(xù)運(yùn)行,即WaitOne方法的線程不在阻塞;
(3)WaitOne方法:阻塞當(dāng)前線程,直到當(dāng)前的等待句柄收到信號(hào)。此方法將一直使本線程處于阻塞狀態(tài)直到收到信號(hào)為止,即當(dāng)其他非阻塞進(jìn)程調(diào)用set方法時(shí)可以繼續(xù)執(zhí)行。
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// 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(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
上述代碼的邏輯為:
(1)試用了ManualRestEvent對(duì)象創(chuàng)建一個(gè)等待句柄,在調(diào)用BeginAccept方法前使用Rest方法允許其他線程阻塞;
(2)為了防止在連接完成之前對(duì)套接字進(jìn)行讀寫(xiě)操作,務(wù)必要在BeginAccept方法后調(diào)用WaitOne來(lái)讓線程進(jìn)入阻塞狀態(tài)。
當(dāng)有連接接入后系統(tǒng)會(huì)自動(dòng)調(diào)用會(huì)調(diào)用回調(diào)函數(shù),所以當(dāng)代碼執(zhí)行到回調(diào)函數(shù)時(shí)說(shuō)明連接已經(jīng)成功,并在函數(shù)的第一句就調(diào)用Set方法讓處于等待的線程可以繼續(xù)執(zhí)行。
四、實(shí)例
下面是一個(gè)實(shí)例,客戶(hù)端請(qǐng)求連接,服務(wù)器端偵聽(tīng)端口,當(dāng)連接建立之后,服務(wù)器發(fā)送字符串給客戶(hù)端,客戶(hù)端收到后并回發(fā)給服務(wù)器端。
服務(wù)器端代碼:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// 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(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
客戶(hù)端代碼:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
// State object for receiving data from remote device.
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 11000;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
// The response from the remote device.
private static String response = String.Empty;
private static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve("user");
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client, "This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
}
五、實(shí)驗(yàn)結(jié)果
圖1 服務(wù)器端界面
圖2 客戶(hù)端界面
上一篇:C#中如何在Excel工作表創(chuàng)建混合型圖表實(shí)例
欄 目:C#教程
下一篇:MessageBox的Buttons和三級(jí)聯(lián)動(dòng)效果
本文標(biāo)題:基于C#的socket編程的TCP異步的實(shí)現(xiàn)代碼
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/6182.html
您可能感興趣的文章
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并打開(kāi)的方法
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#停止線程的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新聞效果的方法
- 01-10C#通過(guò)重寫(xiě)Panel改變邊框顏色與寬度的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已安裝軟件變化的方法
- 01-10C#實(shí)現(xiàn)多線程下載文件的方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫(xiě)Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置


