int port = 1234;網絡
int port = 1234;
IPAddress ip = IPAddress.Parse("127.0.0.1");
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(ip,port);
//socket.Blocking = false;
socket.Bind(iep);
socket.Listen(10);
Console.WriteLine("start......");
try
{
for (int i = 0; i < 10;i++ )
{
}
}
catch
{
Console.WriteLine("異常!");
socket.Close();
}多線程
接收端
private void Receive(Socket socket)
{
NetworkStream ns = new NetworkStream(socket);
FileStream fs = new FileStream("c:\\file.txt", FileMode.OpenOrCreate);
bool isRead = true;
while (isRead)
{
int count = ns.Read(this._receiveBuf, 0, this._receiveBuf.Length);
int datanum = 0;
datanum = BitConverter.ToInt32(this._receiveBuf, 0); //從buffer中的前4個字節讀出count
if (datanum > 0) //肯定每次要接受多少字節數
{
fs.Write(this._receiveBuf, 4, datanum);
}
else //若是接受字節數爲0 就推出
{
isRead = false;
}
}
this.txtFile.Text = "文件傳輸成功";
fs.Close();
}
---------------------
發送端
private void btSend_Click(object sender, System.EventArgs e)
{
if (this._isConnect)
{
_ns = _tc.GetStream();
string path = this.txtPath.Text.Trim();
FileStream fs = new FileStream(path, FileMode.Open);
int sendCount = 0;
byte[] countbuffer = null;
byte[] clientbuffer = new byte[1004];
while (sendCount < fs.Length && _ns.CanWrite)
{
int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //讀出要發送的數據
countbuffer = BitConverter.GetBytes(count);
countbuffer.CopyTo(clientbuffer,0);
_sendBuf.CopyTo(clientbuffer, 4);
this._ns.Write(clientbuffer, 0, 4 + count); //寫入網絡流
sendCount += count;
}
countbuffer = BitConverter.GetBytes(0); //發送完文件後 發送count = 0
this._ns.Write(countbuffer, 0, countbuffer.Length); //使接收端中止
_ns.Close();
fs.Close();
}
}異步
你爲何不把這兩種方案結合在一塊兒呢?
首先把文件的總長度和每次發送的大小先發送出去,等接收端接受並分析,而後開始。
好比每次發送4K(這是操做系統文件管理中使用到的最小文件大小,你能夠看看你係統中的任何一個文件,佔用空間都是4K的整數倍),
最後一次可能會少與4K,可是接受方是能夠計算出來的。
必要時,你可使用多線程,分段發送,接收端收集後分段組合,這還要多使用一個段號碼。
socket是最底層的類,傳輸效率最高!
對於你說的異步操做,一句話說不清楚,基本上能夠用「非阻塞模型」來歸納,就是調用後立馬返回,不是等到操做完成後才返回!
打個比方:阻塞模型
while(isok)
{
readdata(data);//從文件讀數據
send(data); //一直等到data發送完畢後才返回,其實這期間原本能夠進行下一次讀操做
//影響了效率。
if(讀完)
isok=false;
else
isok=true;
}
非阻塞模型,能夠在發送過程當中進行讀取操做,提升了效率。
固然,在第二次發送前,必須等待第一次發送操做完成才行,須要檢測和控制!socket
BeginReceiveFrom 方法啓動從遠程主機異步讀取無鏈接數據報的操做。調用 BeginReceiveFrom 方法將使您可以在單獨的執行線程中接收數據。
您能夠建立一個實現 AsyncCallback 委託的回調方法並將它的名稱傳遞給 BeginReceiveFrom 方法。爲此,您的 state 參數至少必須包含用於通訊的已鏈接或默認 Socket。若是您的回調須要更多信息,則能夠建立一個小型類來保存 Socket 和其餘必需的信息。經過 state 參數將此類的一個實例傳遞給 BeginReceiveFrom 方法。
回調方法應調用 EndReceiveFrom 方法。當應用程序調用 BeginReceiveFrom 時,系統將會使用單獨的線程來執行指定的回調方法,並將在 EndReceiveFrom 上一直阻止到 Socket 讀取數據或引起異常爲止。若是想要在調用 BeginReceiveFrom 方法後使原始線程阻止,請使用 WaitHandle.WaitOne。當須要原始線程繼續執行時,請在回調方法中調用 T:System.Threading.ManualResetEvent 的 Set 方法。有關如何編寫 callback 方法的其餘信息,請參見 Callback 示例。
注意
在調用 BeginReceiveFrom 以前,必須使用 Bind 方法顯式地將 Socket 綁定到本地終結點,不然 BeginReceiveFrom 將會引起 SocketException。
該方法將數據讀入 buffer 參數中,並捕獲從其發送數據的遠程主機終結點。有關如何檢索此終結點的信息,請參考 EndReceiveFrom。若是打算從未知主機或多個主機異步接收無鏈接的數據報,則最適合使用此方法。在這些狀況下, BeginReceiveFrom 將會讀取本地網絡緩衝區接收到的第一個排隊數據報。若是您接收到的數據報大於 buffer 的大小,則 BeginReceiveFrom 方法將在 buffer 中儘量多地填充消息內容,並引起 SocketException。若是您使用的是不可靠協議,多餘的數據將會丟失。而若是當前使用的是可靠協議,則服務提供程序將保留多餘的數據,並且通 過使用一個足夠大的緩衝區調用 BeginReceiveFrom 方法來檢索這些數據。
雖然 BeginReceiveFrom 是用於無鏈接協議的,但您一樣可使用面向鏈接的協議。若是選擇這樣作,則必須經過調用 Connect / BeginConnect 方法來創建遠程主機鏈接,或者調用 Accept 或 BeginAccept 方法來接受傳入的鏈接請求。若是在創建鏈接或接受鏈接以前就調用了 BeginReceiveFrom 方法,則您將獲得 SocketException。您也能夠在調用 BeginReceiveFrom 方法以前,爲無鏈接協議創建默認遠程主機。在上述任何一種狀況下,BeginReceiveFrom 方法都會忽略 remoteEP 參數,而且只從已鏈接的或默認的遠程主機接收數據。
對於面向鏈接的套接字,BeginReceiveFrom 將讀取全部可用的數據,直到達到 size 參數所指定的字節數。
若要取消掛起的 BeginReceiveFrom,請調用 Close 方法。
下面的代碼示例異步接收來自遠程主機的無鏈接數據報。
C# code
IPHostEntry lipa = Dns.Resolve("host.contoso.com");
IPEndPoint lep = new IPEndPoint(lipa.AddressList[0], 11000);
Socket s = new Socket(lep.Address.AddressFamily,
SocketType.Dgram,
ProtocolType.Udp);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
s.Connect(sender);
try{
while(true){
allDone.Reset();
StateObject so2 = new StateObject();
so2.workSocket = s;
Console.WriteLine("Attempting to Receive data from host.contoso.com");
s.BeginReceiveFrom(so2.buffer, 0, StateObject.BUFFER_SIZE,0, ref tempRemoteEP,
new AsyncCallback(Async_Send_Receive.ReceiveFrom_Callback), so2);
allDone.WaitOne();
}
}
catch (Exception e){
Console.WriteLine(e.ToString());
}ide
在端口 11000 上創建 UdpClient 鏈接。將很短的字符串消息發送到兩個單獨的遠程主機。Receive 方法在接收消息前阻止執行。使用傳遞給 Receive 的 IPEndPoint 能夠顯示響應主機的標識。
C# code
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient(11000);
try{
udpClient.Connect("www.contoso.com", 11000);
// Sends a message to the host to which you have connected.
Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
udpClient.Send(sendBytes, sendBytes.Length);
// Sends a message to a different host using optional hostname and port parameters.
UdpClient udpClientB = new UdpClient();
udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);
//IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
// Uses the IPEndPoint object to determine which of these two hosts responded.
Console.WriteLine("This is the message you received " +
returnData.ToString());
Console.WriteLine("This message was sent from " +
RemoteIpEndPoint.Address.ToString() +
" on their port number " +
RemoteIpEndPoint.Port.ToString());
udpClient.Close();
udpClientB.Close();
}
catch (Exception e ) {
Console.WriteLine(e.ToString());
}函數