A. 關於vb.net中socket編程實例:伺服器端的一些問題
Socket類連接後 可以通過類中的 RemoteEndPoint 來獲取遠程IP和埠信息.
要注意的是.需要將它強制轉化為 IPEndPoint類型 然後通過 IPEndPoint.Address以及IPEndPoint.Port來獲取對應的IP及埠
例:
Dim REV_SCK As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
'這里創建一個UDP Socket連接的實例 TCP也是一樣的
'省略SOCKET連接的代碼 當SOCKET連接成功後 可以用下面的語句獲取遠程信息
Dim IP as string ,Port as integer
'定義IP和Port變數 用來保存地址及埠
IP = IPAddress.Parse(CType(REV_SCK.RemoteEndPoint, IPEndPoint).Address.ToString())
Port = IPAddress.Parse(CType(REV_SCK.RemoteEndPoint, IPEndPoint).Port)
B. socket實現過程,具體用的方法;怎麼實現非同步socket
基於C#的socket編程的TCP非同步實現
一、摘要
本篇博文闡述基於TCP通信協議的非同步實現。
二、實驗平台
Visual Studio 2010
三、非同步通信實現原理及常用方法
3.1 建立連接
在同步模式中,在伺服器上使用Accept方法接入連接請求,而在客戶端則使用Connect方法來連接伺服器。相對地,在非同步模式下,伺服器可以使用BeginAccept方法和EndAccept方法來完成連接到客戶端的任務,在客戶端則通過BeginConnect方法和EndConnect方法來實現與伺服器的連接。
BeginAccept在非同步方式下傳入的連接嘗試,它允許其他動作而不必等待連接建立才繼續執行後面程序。在調用BeginAccept之前,必須使用Listen方法來偵聽是否有連接請求,BeginAccept的函數原型為:
BeginAccept(AsyncCallback AsyncCallback, Ojbect state)
參數:
AsyncCallBack:代表回調函數
state:表示狀態信息,必須保證state中包含socket的句柄
使用BeginAccept的基本流程是:
(1)創建本地終節點,並新建套接字與本地終節點進行綁定;
(2)在埠上偵聽是否有新的連接請求;
(3)請求開始接入新的連接,傳入Socket的實例或者StateOjbect的實例。
參考代碼:
復制代碼
//定義IP地址
IPAddress local = IPAddress.Parse("127.0,0,1");
IPEndPoint iep = new IPEndPoint(local,13000);
//創建伺服器的socket對象
Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
server.Bind(iep);
server.Listen(20);
server.BeginAccecpt(new AsyncCallback(Accept),server);
復制代碼
當BeginAccept()方法調用結束後,一旦新的連接發生,將調用回調函數,而該回調函數必須包括用來結束接入連接操作的EndAccept()方法。
該方法參數列表為 Socket EndAccept(IAsyncResult iar)
下面為回調函數的實例:
復制代碼
void Accept(IAsyncResult iar)
{
//還原傳入的原始套接字
Socket MyServer = (Socket)iar.AsyncState;
//在原始套接字上調用EndAccept方法,返回新的套接字
Socket service = MyServer.EndAccept(iar);
}
復制代碼
至此,伺服器端已經准備好了。客戶端應通過BeginConnect方法和EndConnect來遠程連接主機。在調用BeginConnect方法時必須注冊相應的回調函數並且至少傳遞一個Socket的實例給state參數,以保證EndConnect方法中能使用原始的套接字。下面是一段是BeginConnect的調用:
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方法的非同步連接誒遠程主機的請求。在注冊了回調函數後必須接收BeginConnect方法返回的IASynccReuslt作為參數。下面為代碼演示:
復制代碼
void Connect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
復制代碼
除了採用上述方法建立連接之後,也可以採用TcpListener類裡面的方法進行連接建立。下面是伺服器端對關於TcpListener類使用BeginAccetpTcpClient方法處理一個傳入的連接嘗試。以下是使用BeginAccetpTcpClient方法和EndAccetpTcpClient方法的代碼:
復制代碼
public static void DoBeginAccept(TcpListener listner)
{
//開始從客戶端監聽連接
Console.WriteLine("Waitting for a connection");
//接收連接
//開始准備接入新的連接,一旦有新連接嘗試則調用回調函數DoAcceptTcpCliet
listner.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpCliet), listner);
}
//處理客戶端的連接
public static void DoAcceptTcpCliet(IAsyncResult iar)
{
//還原原始的TcpListner對象
TcpListener listener = (TcpListener)iar.AsyncState;
//完成連接的動作,並返回新的TcpClient
TcpClient client = listener.EndAcceptTcpClient(iar);
Console.WriteLine("連接成功");
}
復制代碼
代碼的處理邏輯為:
(1)調用BeginAccetpTcpClient方法開開始連接新的連接,當連接視圖發生時,回調函數被調用以完成連接操作;
(2)上面DoAcceptTcpCliet方法通過AsyncState屬性獲得由BeginAcceptTcpClient傳入的listner實例;
(3)在得到listener對象後,用它調用EndAcceptTcpClient方法,該方法返回新的包含客戶端信息的TcpClient。
BeginConnect方法和EndConnect方法可用於客戶端嘗試建立與服務端的連接,這里和第一種方法並無區別。下面看實例:
復制代碼
public void doBeginConnect(IAsyncResult iar)
{
Socket client=(Socket)iar.AsyncState;
//開始與遠程主機進行連接
client.BeginConnect(serverIP[0],13000,requestCallBack,client);
Console.WriteLine("開始與伺服器進行連接");
}
private void requestCallBack(IAsyncResult iar)
{
try
{
//還原原始的TcpClient對象
TcpClient client=(TcpClient)iar.AsyncState;
//
client.EndConnect(iar);
Console.WriteLine("與伺服器{0}連接成功",client.Client.RemoteEndPoint);
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
}
}
復制代碼
以上是建立連接的兩種方法。可根據需要選擇使用。
3.2 發送與接受數據
在建立了套接字的連接後,就可以伺服器端和客戶端之間進行數據通信了。非同步套接字用BeginSend和EndSend方法來負責數據的發送。注意在調用BeginSend方法前要確保雙方都已經建立連接,否則會出異常。下面演示代碼:
復制代碼
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());
}
}
復制代碼
接收數據是通過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)首先處理連接的回調函數里得到的通訊套接字client,接著開始接收數據;
(2)當數據發送到緩沖區中,BeginReceive方法試圖從buffer數組中讀取長度為buffer.length的數據塊,並返回接收到的數據量bytesRead。最後接收並列印數據。除了上述方法外,還可以使用基於NetworkStream相關的非同步發送和接收方法,下面是基於NetworkStream相關的非同步發送和接收方法的使用介紹。
NetworkStream使用BeginRead和EndRead方法進行讀操作,使用BeginWreite和EndWrete方法進行寫操作,下面看實例:
復制代碼
static void DataHandle(TcpClient client)
{
TcpClient tcpClient = client;
//使用TcpClient的GetStream方法獲取網路流
NetworkStream ns = tcpClient.GetStream();
//檢查網路流是否可讀
if(ns.CanRead)
{
//定義緩沖區
byte[] read = new byte[1024];
ns.BeginRead(read,0,read.Length,new AsyncCallback(myReadCallBack),ns);
}
else
{
Console.WriteLine("無法從網路中讀取流數據");
}
}
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));
//接收到的消息長度可能大於緩沖區總大小,反復循環直到讀完為止
while (ns.DataAvailable)
{
ns.BeginRead(read, 0, read.Length, new AsyncCallback(myReadCallBack), ns);
}
//列印
Console.WriteLine("您收到的信息是" + data);
}
復制代碼
3.3 程序阻塞與非同步中的同步問題
.Net里提供了EventWaitHandle類來表示一個線程的同步事件。EventWaitHandle即事件等待句柄,他允許線程通過操作系統互發信號和等待彼此的信號來達到線程同步的目的。這個類有2個子類,分別為AutoRestEevnt(自動重置)和ManualRestEvent(手動重置)。下面是線程同步的幾個方法:
(1)Rset方法:將事件狀態設為非終止狀態,導致線程阻塞。這里的線程阻塞是指允許其他需要等待的線程進行阻塞即讓含WaitOne()方法的線程阻塞;
(2)Set方法:將事件狀態設為終止狀態,允許一個或多個等待線程繼續。該方法發送一個信號給操作系統,讓處於等待的某個線程從阻塞狀態轉換為繼續運行,即WaitOne方法的線程不在阻塞;
(3)WaitOne方法:阻塞當前線程,直到當前的等待句柄收到信號。此方法將一直使本線程處於阻塞狀態直到收到信號為止,即當其他非阻塞進程調用set方法時可以繼續執行。
復制代碼
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對象創建一個等待句柄,在調用BeginAccept方法前使用Rest方法允許其他線程阻塞;
(2)為了防止在連接完成之前對套接字進行讀寫操作,務必要在BeginAccept方法後調用WaitOne來讓線程進入阻塞狀態。
當有連接接入後系統會自動調用會調用回調函數,所以當代碼執行到回調函數時說明連接已經成功,並在函數的第一句就調用Set方法讓處於等待的線程可以繼續執行
C. 關於.net裡面的socket知識
1.什麼是socket
所謂socket通常也稱作"套接字",應用程序通常通過"套接字"向網路發出請求或者應答網路請求。 以J2SDK-1.3為例,Socket和ServerSocket類庫位於java .net包中。ServerSocket用於伺服器端,Socket是建立網路連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話鏈數。對於一個網路連接來說,套接字是平等的,並沒有差別,不因為在伺服器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
重要的Socket API
重要的Socket API:java .net.Socket繼承於java.lang.Object,有八個構造器,其方法並不多,下面介紹使用最頻繁的三個方法,其它方法大家可以見JDK-1.3文檔。
Accept方法用於產生"阻塞",直到接受到一個連接,並且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。
getInputStream方法獲得網路連接輸入,同時返回一個InputStream對象實例。
getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。 注意:其中getInputStream和getOutputStream方法均可能會產生一個IOException,它必須被捕獲,因為它們返回的流對象,通常都會被另一個流對象使用。
2.如何開發一個Server-Client模型的程序
開發原理:
伺服器,使用ServerSocket監聽指定的埠,埠可以隨意指定(由於1024以下的埠通常屬於保留埠,在一些操作系統中不可以隨意使用,所以建議使用大於1024的埠),等待客戶連接請求,客戶連接後,會話產生;在完成會話後,關閉連接。
客戶端,使用Socket對網路上某一個伺服器的某一個埠發出連接請求,一旦連接成功,打開會話;會話完成後,關閉Socket。客戶端不需要指定打開的埠,通常臨時的、動態的分配一個1024以上的埠。
Socket介面是TCP/IP網路的API,Socket介面定義了許多函數或常式,程序員可以用它們來開發TCP/IP網路上的應用程序。要學Internet上的TCP/IP網路編程,必須理解Socket介面。 Socket介面設計者最先是將介面放在Unix操作系統裡面的。如果了解Unix系統的輸入和輸出的話,就很容易了解Socket了。網路的Socket數據傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似於打開文件的函數調用Socket(),該函數返回一個整型的Socket描述符,隨後的連接建立、數據絕知傳輸等操作都是通過該Socket實現的。
常用的Socket類型
有兩種:流式Socket(SOCK_STREAM)和數據報式Socket(SOCK_DGRAM)。流式是一種面向連接的Socket,針對於面向連接的TCP服務應用;數據報式Socket是一種無連接的Socket,對應於無連接的UDP服務應用。 Socket建立為了建立Socket,程序可以調用Socket函數,該函數返回一個類似於文件描述符的句柄。socket函數原型為:int socket(int domain, int type, int protocol);domain指明所使用的協議族,通常為AF_INET,表示互聯網協議族(TCP/IP協議族);type參數指定socket的類型:SOCK_STREAM 或SOCK_DGRAM,Socket介面還定義了原始Socket(SOCK_RAW),允許程序使用低層協議;protocol通常賦值0。Socket()調用返回一個整型socket描述符,你可並喚消以在後面的調用使用它。 Socket描述符是一個指向內部數據結構的指針,它指向描述符表入口。調用Socket函數時,socket執行體將建立一個Socket,實際上"建立一個Socket"意味著為一個Socket數據結構分配存儲空間。 Socket執行體為你管理描述符表。兩個網路程序之間的一個網路連接包括五種信息:通信協議、本地協議地址、本地主機埠、遠端主機地址和遠端協議埠。Socket數據結構中包含這五種信息。 socket在測量軟體中的使用也很廣泛
D. vb.net中Socket問題
1.綁定的IP是伺服器的IP地址,伺服器是固輪穗定的,客戶端連接的是一個已知的伺服器端。
2.客戶端的話,連接到伺服器時爛桐攜,伺服器accept後,就可以獲得客戶端的連接信息,包括IP地址和埠。
我是學C的,在C語言中,socket->bind->listen->accept->....,在accept函數中有選項,如下caddr結構體中就存有accept後客戶端的IP地址 連接埠和傳輸方式等信息,clientsock[1]則為飢伏accept新的描述符,如你程序中soc2一樣 。
clientsock[1] = accept(sfd,(struct sockaddr*)&caddr,&len);
VB中應該也有類時的函數,你網上好好找一下,或者看看相關書籍.
E. 如何實現vb.net的socket雙向通訊,客戶端既要發送消息也要接收伺服器端返回的結果
接收到客戶端數據,處理完畢........
//返回信息給客戶端
string sendStr = "ok!Client send message successful!";
byte[] bs = Encoding.ASCII.GetBytes(sendStr);
client.Send(bs, bs.Length, 0);
//關閉套接字
client.Close();
.............客戶端發送完數據等待服務端返回處理結果.............
/**/
///接受從伺服器返回的信息
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = client.Receive(recvBytes, recvBytes.Length, 0);//從伺服器端接受返回信息
recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
label15.Text = DateTime.Now.ToString() + ":" + recvStr;//顯示伺服器返回信息
///一定記著用完socket後要關閉
//關閉套接字
client.Close();
F. socket通信原理
socket通信原理是一種「打開—讀/寫—關閉」模式的實現,伺服器和客戶端各自維護一個「文件」,在建立連接打開後,可以棚氏向文件寫入內容供對方讀取或者讀取對方內容,通訊結束時關閉文件。
Socket在應用層和傳輸層之間的一個抽象層,它把 TCP/IP 層復雜的操作抽象為幾個簡單的介面,供應用層調用實現進程在網路中的通信。Socket 起源於 UNIX,在 UNIX 一切皆文件的思想下,進程間通信就被冠名為文件描述符(file descriptor)。
Socket 保證了不同計算機之間的通信,也就是網路通信。對於網站,通信模型是伺服器與客戶端之間的通信。兩端都建立了一個 Socket 對象,然後通過 Socket 對象對數據進行傳輸。通常鏈遲散伺服器處於一個無限循環,等待客戶端的連接。
(6)vbnetsocket編程原理擴展閱讀
SOCK_STREAM類型的套介面為全雙向的位元組流。對於流類套介面,在接收或發送數據前必需處於已連接狀態。用connect()調用建立與另一套介面的連接,連接成功後,即可用send()和recv()傳送數據。當會話結束後,調用closesocket()。帶外數據根據規定用send()和recv()來接收。
實現SOCK_STREAM類型套介面的通訊協議保證數據不會丟失也不會重復。如果終端協議有緩沖區空間,且數據不能在一定時間成功發送旦襪,則認為連接中斷,其後續的調用也將以WSAETIMEOUT錯誤返回。
SOCK_DGRAM類型套介面允許使用sendto()和recvfrom()從任意埠發送或接收數據報。如果這樣一個套介面用connect()與一個指定埠連接,則可用send()和recv()與該埠進行數據報的發送與接收。
G. VB.net Socket
麻煩給我發下vb2010下Socket類的使用方法,最好是有代碼。就是怎樣實現同一台電腦上兩個程序的通訊,1窗體有按鈕,文本框,2窗體有文本框,當單機1窗體的按鈕時該窗體文本框的內容在2窗體的文本框中顯示。。。十萬火急啊。 郵箱[email protected]
H. 關於vb.net中Socket的問題
我不給你代碼了,我才編了SOCKET的,告訴你原理吧(我的編程經驗而已)
SOCKET傳輸文件和接受是有大小限制的,默認是81**來則也就是8K多,你可以改小,但改大我沒試過,然後你必須把文件分成若干份,然後傳過去,然後在接收端組合起來,同時接收端的接受大小要和發送大小統一。
至於你說的文件名,文件名不屬於文件數據中的一部分,它不參與數據傳輸的,你只能在接收端重新改名字。
同時為什麼要用上面的方法傳呢,因為VB.NET中的SOCKET有很多問題,我就為此煩過,因為要丟包(理論上TCP不存在),或者粘包,或者斷包,也就是你在接收端獲取文件時數據是要出錯的,比如你定長3000B,結果接收端可能先收到2000B,當接受端接受後,處理會出錯的。
所以SOCKET的標准發送方法是建立定長的結構體(結構體必須定義為可序列化結構體),最好結構體裡面至少包含有 1,文件名,2,本包序號,3,本包數據,比如每個包大小3040B,文件名佔20,序號佔20,數據佔3000,然後發送出去,接收端每次固定接受3040B,如果接受到的包沒有這么大(比如收到2000),那麼繼續接受(1040),直到達到3040後組合成一個包,在把包分解成結構體,相同的文件名為一個文件,再按照序號按次組合其中的數據,這就完成了傳輸。這樣的方法還可以同時傳送多個文件,因為結構體裡麵包含了文件名和序列號,不會錯亂,如果是大文件,請不要接收完畢後(最後一個包的序號可以為-1,或者包里包含總長度,檢查到序號為-1時表示完畢,或者達到總長度後表示完畢)再組合,因為這樣會浪費電腦內存,最好的方法是一邊接受數據,一邊寫入到文件中(收到第一個包時就建立文件,以後每個包的數據都往裡面寫)。
回答你的問題:
1、經過上面的傳輸後,文件是不變化的,MD5檢查都是正常的,不用擔心文件大小有變化(如果有變化,那就是代碼沒編對)
2,、文件名問題,我前面提到了,文件名是不參與傳輸的,它不屬於數據中的一部分,比如同一個文件,不管你怎麼改名字MD5是不變的。你只能通過把文件名想辦法傳給對方(比如我上面說的結構體方法),讓對方寫入文件時使用。
3,代碼:
還是給你找找吧,等等
不行,我的都很大,很長,你還是在網上找吧,有很多例子,我也是網上學的。
I. 什麼是socket網路編程
使用socket套接字,利用TCP/IP或者UDP協議,實現幾個機器之間的通信。一般使用C/S結構。
以TCP/IP為例:首先建立一個伺服器,步驟如下:socket()創建一個socket,bind()綁定socket到一個埠,listen()監聽埠,accept()等待客戶端的連接。客戶端程序:socket()創建一個socket,可以綁定也可以不綁定,然後connect()連接到伺服器端。socket又分為阻塞式的和非阻塞式的。阻塞式的就是伺服器端等待連接直到連接上,不然一直掛起。