C#培訓2019-11-15 Socket 實現兩個應用之間通信(相同/不同主機之間)

Socket利用TCP/IP通信方法,實現一臺主機中兩個應用通信,或者多臺主機中應用的通信。
引用using System.Net.Sockets; using System.Net;
1、Server端設置:Server端主要是用來監聽Client端是否有連接的。範例代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace Serve
{
	class Program
	{
		static void Main( string[] args )
		{
			Socket socket = new Socket(
				AddressFamily.InterNetwork,// ipv4
				SocketType.Stream,// 串流
				ProtocolType.Tcp );// tcp協議,有時候會用udp
			// serve要綁定主機的ip地址
			IPEndPoint endPoint = new IPEndPoint( IPAddress.Any, 5678 );//準備一個端口,IPAddress.Any 表示可能有雙網卡,都會綁定
			socket.Bind( endPoint );

			socket.Listen( 100 );//聽client連線,100表示同時可以檢測100個

			//當client連線後,需要處理。只有連線時,纔會執行這一步,
			//又創建一個Socket來執行數據的接受和發送
			Socket acceptSocket = socket.Accept();

			byte[] buffer = new byte[ 100 ];
			
			// 連接上以後如果沒有接受到資料,就會停在這裏等待,直到接受到長度爲100的byte(可以選擇自定義長度的重載方法)
			//可以一直resive,上一次resive完後,還是在連接狀態
			//常用的是接受一個封包,要解析,接受長度是根據解析封包長度來定
			acceptSocket.Receive( buffer );

			for( int i = 0; i < buffer.Length; i++ ) {
				Console.Write( buffer[i].ToString() );
			}
			// 發送給Client數據
			byte[] SendBuffer = new byte[ 100 ];
			for( int i = 0; i < 100; i++ ) {
				SendBuffer[ i ] = (byte)(i+100);
			}
			acceptSocket.Send( SendBuffer );
			Console.ReadLine();
		}
	}
}

2、Client端設置:Client端主要是用來連接Server端,連接上後可以和Server端相互傳輸數據。範例代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace Client
{
	class Program
	{
		static void Main( string[] args )
		{
			Socket socket = new Socket(
				AddressFamily.InterNetwork,
				SocketType.Stream,
				ProtocolType.Tcp );
			//IPEndPoint endPoint = new IPEndPoint();
			//socket.Connect( "18.18.90.197", 5678 );//127.0.0.1是本地端連接ip,此處的端口號要與Server端口號相同,IP可以是外網ip也可以是本機ip
			socket.Connect( "127.0.0.1", 5678 );//也是可以的

			// 此時就是這socket和外部連接溝通
			byte[] buffer = new byte[ 100 ];
			for( int i = 0; i < 100; i++ ) {
				buffer[i] = (byte)i;
			}
			socket.Send( buffer );//發送給Server數據
			
			byte[] ReceiveBuffer = new byte[ 100 ];
			socket.Receive( ReceiveBuffer );//接受Server傳過來的數據
			for( int i = 0; i < ReceiveBuffer.Length; i++ ) {
				Console.Write( ReceiveBuffer[ i ].ToString() );
			}
			Console.ReadLine();
		}
	}
}

3、注意事項
①當Server端接到連接後,會執行下一步動作,此時若又另一個連接過來,也會連上。因此一般會用邏輯或其他方式(線程)來單獨處理每一個連接。
②查看電腦端口情況CMD代碼:netstat -na
③Server端和Client端之間發送的數據只能是 byte[],若要發送字串需要編碼和解碼,如:
            String string1 = "測試數據123測試數據ABC";
            byte[] buffer = new byte[2048];

			//編碼後才能發送字符串
            buffer = Encoding.Default.GetBytes(string1);

            Socket socket = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            socket.Connect("127.0.0.1", 5678);
            socket.Send(buffer);
            socket.Close();
            MessageBox.Show("發送完畢");
當然同樣的接受到的 byte[]也要解碼成字符串,才能正常顯示,如:
			byte[] buffer = new byte[ 1024 ];
			acceptSocket.Receive( buffer );
			
			// 下面就是利用Encoding.Default.GetString()方法來解碼的
			Console.Write( Encoding.Default.GetString( buffer ) );
④若發送的長度較長(eg:100),接收的變量長度較短(eg:10),則會一次性接收不完,下一次遇到acceptSocket.Receive( buffer );的時候會繼續接收上一次沒接收完的信息,知道把上一次的完全接收完畢。(例如100長度的發送,用10長度接收,需要接收10次,而不是接收不下直接捨去。)
4、一般使用:
①解決線程調用方法傳值:調用時如果需要傳入參數,可以通過實例化類來避免這件事,如每次都是實例化類,在建構子中傳入參數,然後定義字段。並且在建構子中開新的線程。
②解決編碼後長度改變:每次編碼後,用數組的CopyTo/Clone方法淺拷貝到另一個固定長度的buffer來裝,這樣就能保證發送的長度固定了。
③接收固定長度,爲了保證每次Receive的長度爲固定長度,找到方法的定義,public int Receive( byte[] buffer );,發現返回值爲:已經接收的長度。(一般情況下,如果發送的長度等於接收的長度,並且發送是一次性發送完的不會有接收不滿的情況)可以利用這個返回值,來保證接收到固定長度才停止接收。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章