同步套接字通信
Socket支持下(xià)的網上點對點的通信
服務端實現監聽(tīng)連接,客戶端實現發送連接請求,建立連接後進行發送和接收數據的功能
服務器端建立一(yī)個socket,設置好本機的ip和監聽(tīng)的端口與socket進行綁定,開(kāi)始監聽(tīng)連接請求,當接收到連接請求後,發送确認,同客戶端建立連接,開(kāi)始與客戶端進行通信。
客戶端建立一(yī)個socket,設置好服務器端的IP和提供服務的端口,發出連接請求,接收到服務的确認後,盡力連接,開(kāi)始與服務器進行通信。
服務器端和客戶端的連接及它們之間的數據傳送均采用同步方式。
Socket
Socket是tcp\ip網絡協議接口。内部定義了許多的函數和例程。可以看成是網絡通信的一(yī)個端點。在網絡通信中(zhōng)需要兩個主機或兩個進程。通過網絡傳遞數據,程序在網絡對話(huà)的每一(yī)端需要一(yī)個socket。
Tcp/IP傳輸層使用協議端口将數據傳送給一(yī)個主機的特定應用程序,協議端口是一(yī)個應用程序的進程地址。傳輸層模塊的網絡軟件模塊要于另一(yī)個程序通信,它将使用協議端口,socket是運行在傳輸層的api,使用socket建立連接發送數據要指定一(yī)個端口給它。
Socket:
Stream Socket流套接字 Socket提供雙向、有序、無重複的數據流服務,出溜大(dà)量的網絡數據。
Dgram socket數據包套接字 支持雙向數據流,不保證傳輸的可靠性、有序、無重複。
Row socket 原始套接字 訪問底層協議
建立socket 用C#
命名空間:using System.Net;using System.Net.Socket;
構造新的socket對象:socket原型:
Public socket (AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)
AddressFamily 用來指定socket解析地址的尋址方案。InterNetwork标示需要ip版本4的地址,InterNetworkV6需要ip版本6的地址
SocketType參數指定socket類型Raw支持基礎傳輸協議訪問,Stream支持可靠,雙向,基于連接的數據流。
ProtocolType表示socket支持的網絡協議
定義主機對象:
IPEndPoint類:IPEndPoint構造方法 位置:System.Net
原型:1) public IPEndPoint(IPAddress address,int port) 2)public IPEndPoint(long address,int port) 參數1整型int64如123456,參數2端口int32
主機解析:
利用DNS服務器解析主機,使用Dns.Resolve方法
原型:public static IPHostEntry Resolve(string hostname) 參數:待解析的主機名稱,返回IPHostEntry類值,IPHostEntry爲Internet主機地址信息提供容器,該容器提供存有IP地址列表,主機名稱等。
Dns.GetHostByName獲取本地主機名稱
原型:public static IPHostEntry GetHostByName(string hostname)
GetHostByAddress
原型:1)public static IPHostEntry GetHostByAddress(IPAddress address) 參數:IP地址 2)public static IPHostEntry GetHostByAddress(string address) IP地址格式化字符串
端口綁定和監聽(tīng):
同步套接字服務器主機的綁定和端口監聽(tīng)
Socket類的Bind(綁定主機),Listen(監聽(tīng)端口),Accept(接收客戶端的連接請求)
Bind:原型:public void Bind(EndPoint LocalEP)參數爲主機對象 IPEndPoint
Listen:原型:public void Listen(int backlog) 參數整型數值,挂起隊列最大(dà)值
accept:原型:public socket accept() 返回爲套接字對象
演示程序:
IPAddress myip=IPAddress.Parse(“127.0.0.1”);
IPEndPoint myserver=new IPEndPoint(myip,2020);
Socket sock=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Sock.Bind(myserver);
Sock.Listen(50);
Socket bbb=sock.Accept();
發送數據:方法1:socket類的send方法二:NetworkStream類Write
send原型:public int Send(byte[] buffer) 字節數組
public int Send(byte[],SocketFlags)原型2說明,SocketFlags成員(yuán)列表:DontRoute(不使用路由表發送),MaxIOVectorLength(爲發送和接收數據的wsabuf結構數量提供标準值)None 不對次調用使用标志(zhì)) OutOfBand(消息的部分(fēn)發送或接收)Partial(消息的部分(fēn)發送或接收) Peek(查看傳入的消息)
原型三:public int Send(byte[],int,SocketFlags) 參數二要發送的字節數
原型四:public int Send(byte[],int,int,SocketFlags) 參數二爲Byte[]中(zhōng)開(kāi)始發送的位置
演示:
Socket bbb=sock.Accept();
Byte[] bytes=new Byte[64];
string send="aaaaaaaaaaaa";
bytes=System.Text.Encoding.BigEndianUnicode.GetBytes(send.ToCharArray());
bbb.Send(bytes,bytes.length,0);//将byte數組全部發送
NetWordStream類的Write方法發送數據
原型:public override void write(byte[] buffer,int offset,int size) 字節數組,開(kāi)始字節位置,總字節數
Socket bbb=sock.Accept();
NetWorkStream stre=new NewWorkStream(bbb);
Byte[] ccc=new Byte[512];
string sendmessage="aaaaaaaaaaaaaa";
ccc=System.Text.Encoding.BigEndianUnicode.GetBytes(sendmessage);
stre.Write(ccc,0,ccc.length);
接收數據:Socket類Receive或NetworkStream類Read
Socket類Receive方法
原型:public int Receive(byte[] buffer)
2)public int Receive(byte[],SocketFlags)
3)public int Receive(byte[],int,SocketFlags)
4)public int Receive(byte[],int,int,SocketFlags)
.....
Socket bbb=sock.Accept();
........
Byte[] ccc=new Byte[512];
bbb.Receive(ccc,ccc.Length,0);
string rece=System.Text.Encoding.BigEndianUnicode.GetString(ccc);
richTextBox1.AppendText(rece+"\r\n");
NetworkStream類的Read方法接收數據
public override int Read(int byte[] buffer,int offset,int size)
演示:bbb=sock.Accept();
.......
NetworkStream stre=new NetworkStream(bbb);
Byte[] ccc=new Byte[512];
stre.Read(ccc,0,ccc.Length);
string readMessage=System.Text.Encoding.BigEndianUnicode.GetString(ccc);
線程
線程創建:System.Threading空間下(xià)的Thread類的構造方法:
原型:public Thread(ThreadStart start) ThreadStart類型值
Thread thread=new Thread(new ThreadStart(accp));
Private void accp(){}//使用線程操作
線程啓動
Thread thread=new Thread(new ThreadStart(accp));
線程暫停與重新啓動
啓動線程使用Thread.Sleep是當前線程阻塞一(yī)段時間Thread.Sleep(Timeout.Infinite)是線程休眠,直到被調用Thread.Interrrupt的另一(yī)個線程中(zhōng)斷或被Thread.Abort中(zhōng)止。
一(yī)個線程不能對另一(yī)個調用Sleep,可以使用Thread.Suspend來暫停線程,當線程對自身調用Thread.Suspend将阻塞,直到該線程被另一(yī)個線程繼續,當一(yī)個線程對另一(yī)個調用,該調用就成爲使另一(yī)個線程暫停的非阻塞調用。調用Thread.Resume使另一(yī)個線程跳出挂起狀态并使該線程繼續執行,而與調用Thread.Suspend的次數無關
線程休眠:Thread.Sleep(10000);
線程挂起:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Suspend();
重新啓動:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Suspend();
Thread.Resume();
阻塞線程的方法:thread.Join使用一(yī)個線程等待另一(yī)個線程停止
Thread.Join
Public void Join();
Public void Join(int millisecondsTimeout);毫秒
Public bool Join(TimeSpan timeout);時間間隔類型值
實例:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Join(10000);
線程銷毀:
Thread.Abort,Thread.Interrupt
Abort方法引發ThreadAbortException,開(kāi)始中(zhōng)止此線程的過程,是一(yī)個可以由應用程序代碼捕獲的特殊異常,ResetAbort可以取消Abort請求,可以組織ThreadAbortException終止此線程,線程不一(yī)定會立即終止,根本不終止。
對尚未啓動的線程調用Abort,則當調用Start時該線程将終止。對已經挂起的線程調用Abort,則該線程将繼續,然後終止。對阻塞或正在休眠的線程調用Abort,則該線程被中(zhōng)斷,然後終止。
Thread類的Abort方法:
Public void Abort()
Public void Abort(object stateinfo);
演示:
Thread thread=new Thread(new ThreadStart(accp));
Thread.Start();
Thread.Abort();
Thread.Join(10000);
Socket編程原理:
Unix的i/o命令集,模式爲開(kāi)-讀/寫-關 open write/read close
用戶進程進行i/o操作
用戶進程調用打開(kāi)命令,獲取文件或設備的使用權,并返回描述文件或設備的整數,以描述用戶打開(kāi)的進程,該進程進行讀寫操作,傳輸數據,操作完成,進程關閉,通知(zhī)os對哪個對象進行了使用。
Unix網絡應用編程:BSD的套接字socket,unix的System V 的TLI。
套接字編程的基本概念:
網間進程通信:源于單機系統,每個進程在自己的地址範圍内進行運行,保證互相不幹擾且協調工(gōng)作。操作系統爲進程之間的通信提供設施:
Unix BSD 管道pipe,命名管道named pipe軟中(zhōng)斷信号signal
Unix System V 消息message 共享存儲區 shared memory 信号量semaphore
以上僅限于本機進程之間通信。
端口:網絡上可以被命名和尋址的通信端口,是操作系統可以分(fēn)配的一(yī)種資(zī)源,網絡通信的最終地址不是主機地址,是可以描述進程的摸中(zhōng)标識符。TCP/IP提出協議端口porotocol port端口,表示通信進程。
進程通過os調用綁定連接端口,而在傳輸層傳輸給該端口的數據傳入進程中(zhōng)處理,同樣在進程的數據需要傳給傳輸層也是通過綁定端口實現。進程對端口的操作相當于對os中(zhōng)的i/o文件進行操作,每一(yī)個端口也對應着一(yī)個端口号,tcp/ip協議分(fēn)爲tcp和udp,雖然有相同port number的端口,但是互相也不沖突。 端口号的分(fēn)配有全局分(fēn)配,本地分(fēn)配(動态分(fēn)配),當進程需要訪問傳輸層,os分(fēn)配給進程一(yī)個端口号。全局分(fēn)配,就是os固定分(fēn)配的端口,标準的服務器都有固定的全局公認的端口号提供給服務。小(xiǎo)于256的可以作爲保留端口。
地址:網絡通信中(zhōng)的兩台機器,可以不再同一(yī)個網絡,可能間隔(網關,網橋,路由器等),所以可以分(fēn)爲三層尋址
機器在不同的網絡則有該網絡的特定id
同一(yī)個網絡中(zhōng)的機器應該有唯一(yī)的機器id
一(yī)台機器内的進程應該有自己的唯一(yī)id
通常主機地址=網絡ID+主機ID tcp/ip中(zhōng)使用16位端口号來表示進程。
網絡字節順序,高價先存,tcp和udp都使用16或32整數位的高價存儲,在協議的頭文件中(zhōng)。
半相關:在網絡中(zhōng)一(yī)個進程爲協議+本地地址+端口号=三元組,也叫半相關,表示半部分(fēn)。
全相關:兩台機器之間通信需要使用相同協議
協議+本地地址+本地端口号+遠程地址+遠程端口号 五元組 全相關。
順序:兩個連續的報文在網絡中(zhōng)可能不會通過相同的路徑到達,所以接收的順序會和發送的順序不一(yī)緻。順序是接收順序與發送順序一(yī)緻。Tcp/ip提供該功能。
差錯控制:檢查數據差錯:檢查和CheckSum機制 檢查連接差錯:雙方确認應答機制。
流控制:雙方傳輸數據過程中(zhōng),保證數據傳輸速率的機制,保證數據不丢失。
字節流:把傳輸中(zhōng)的報文當作一(yī)個字節序列,不提供任何數據邊界。
全雙工(gōng)/半雙工(gōng):兩個方向發送或一(yī)個方向發送
緩存/帶外(wài)數據:字節流服務中(zhōng),沒有報文邊界,可以同一(yī)時刻讀取任意長度的數據。爲保證傳輸正确或流協議控制,需要使用緩存,交互型的應用程序禁用緩存。
數據傳送中(zhōng),希望不通過常規傳輸方式傳送給用戶以便及時處理的某一(yī)類信息(unix系統的中(zhōng)斷鍵delete,Control-c)、終端流控制符Control-s、Control-q)爲帶外(wài)數據。
客戶/服務器模式主動請求方式:
1. 打開(kāi)通信通道,通知(zhī)本地主機,在某一(yī)個公認地址上接收客戶請求
2. 等待客戶請求到達端口
3. 接收到重複服務請求,處理請求發送應答信号。接收到并發服務請求。要激活一(yī)個新進程處理客戶請求,unix系統fork、exec,新進程處理客戶請求,不需要對其他請求作出應答,服務完成後,關閉此進程與客戶的通信鏈路。終止
4. 返回第二步,等待另一(yī)個客戶請求。
5. 關閉服務端
客戶方:
1. 打開(kāi)一(yī)通信通道,并連接到服務器所在主機的特定端口。
2. 向服務器發送服務請求報文,等待并接收應答;繼續提出請求…….
3. 請求結束以後關閉通信通道并終止。
:
1. 客戶與服務器進程的作用非對稱,編碼不同
2. 服務進程先于客戶請求而啓動,系統運行,服務進程一(yī)緻存在,直到正常退出或強迫退出
套接字類型:
TCP/IP的socket
Sock_stream可靠的面對連接數據傳輸,無差錯、無重複發送,安照順序發送接收,内設流量控制,避免數據流超限,數據爲字節流,無長度限制,ftp流套接字。
Sock_DGRAM 無連接的服務,數據包以獨立包的形式發送,不提供無措保證,數據可能丢失重複,發送接收的順序混亂,網絡文件系統nfs使用數據報式套接字。
Sock_Ram 接口允許較底層協議,IP,ICMP直接訪問,檢查新的協議實現或訪問現有服務中(zhōng)配置的新設備。
服務端:
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
Thread mythread ;
Socket socket;
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
try
{
socket.Close();//釋放(fàng)資(zī)源
mythread.Abort ( ) ;//中(zhōng)止線程
}
catch{ }
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
public static IPAddress GetServerIP()
{
IPHostEntry ieh=Dns.GetHostByName(Dns.GetHostName());
return ieh.AddressList[0];
}
private void BeginListen()
{
IPAddress ServerIp=GetServerIP();
IPEndPoint iep=new IPEndPoint(ServerIp,8000);
socket=new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
byte[] byteMessage=new byte[100];
this.label1.Text=iep.ToString();
socket.Bind(iep);
// do
while(true)
{
try
{
socket.Listen(5);
Socket newSocket=socket.Accept();
newSocket.Receive(byteMessage);
string sTime = DateTime.Now.ToShortTimeString ( ) ;
string msg=sTime+":"+"Message from:";
msg+=newSocket.RemoteEndPoint.ToString()+Encoding.Default.GetString(byteMessage);
this.listBox1.Items.Add(msg);
}
catch(SocketException ex)
{
this.label1.Text+=ex.ToString();
}
}
// while(byteMessage!=null);
}
//開(kāi)始監聽(tīng)
private void button1_Click(object sender, System.EventArgs e)
{
try
{
mythread = new Thread(new ThreadStart(BeginListen));
mythread.Start();
}
catch(System.Exception er)
{
MessageBox.Show(er.Message,"完成",MessageBoxButtons.OK,MessageBoxIcon.Stop);
}
}
客戶端:
using System.Net;
using System.Net.Sockets;
using System.Text;
private void button1_Click(object sender, System.EventArgs e)
{
BeginSend();
}
private void BeginSend()
{
string ip=this.txtip.Text;
string port=this.txtport.Text;
IPAddress serverIp=IPAddress.Parse(ip);
int serverPort=Convert.ToInt32(port);
IPEndPoint iep=new IPEndPoint(serverIp,serverPort);
byte[] byteMessage;
// do
// {
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
socket.Connect(iep);
byteMessage=Encoding.ASCII.GetBytes(textBox1.Text);
socket.Send(byteMessage);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
// }
// while(byteMessage!=null);
}
基于TCP協議的發送和接收端
TCP協議的接收端
using System.Net.Sockets ; //使用到TcpListen類
using System.Threading ; //使用到線程
using System.IO ; //使用到StreamReader類
int port = 8000; //定義偵聽(tīng)端口号
private Thread thThreadRead; //創建線程,用以偵聽(tīng)端口号,接收信息
private TcpListener tlTcpListen; //偵聽(tīng)端口号
private bool blistener = true; //設定标示位,判斷偵聽(tīng)狀态
private NetworkStream nsStream; //創建接收的基本數據流
private StreamReader srRead;
private System.Windows.Forms.StatusBar statusBar1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1; //從網絡基礎數據流中(zhōng)讀取數據
private TcpClient tcClient ;
private void Listen ( )
{
try
{
tlTcpListen = new TcpListener ( port ) ; //以8000端口号來初始化TcpListener實例
tlTcpListen.Start ( ) ; //開(kāi)始監聽(tīng)
statusBar1.Text = "正在監聽(tīng)..." ;
tcClient = tlTcpListen.AcceptTcpClient ( ) ; //通過TCP連接請求
nsStream = tcClient.GetStream ( ) ; //獲取用以發送、接收數據的網絡基礎數據流
srRead=new StreamReader(nsStream);//以得到的網絡基礎數據流來初始化StreamReader實例
statusBar1.Text = "已經連接!";
while( blistener ) //循環偵聽(tīng)
{
string sMessage = srRead.ReadLine();//從網絡基礎數據流中(zhōng)讀取一(yī)行數據
if ( sMessage == "STOP" ) //判斷是否爲斷開(kāi)TCP連接控制碼
{
tlTcpListen.Stop(); //關閉偵聽(tīng)
nsStream.Close(); //釋放(fàng)資(zī)源
srRead.Close();
statusBar1.Text = "連接已經關閉!" ;
thThreadRead.Abort(); //中(zhōng)止線程
return;
}
string sTime = DateTime.Now.ToShortTimeString ( ) ; //獲取接收數據時的時間
listBox1.Items.Add ( sTime + " " + sMessage ) ;
}
}
catch ( System.Security.SecurityException )
{
MessageBox.Show ( "偵聽(tīng)失敗!" , "錯誤" ) ;
}
}
//開(kāi)始監聽(tīng)
private void button1_Click(object sender, System.EventArgs e)
{
thThreadRead = new Thread ( new ThreadStart ( Listen ) );
thThreadRead.Start();//啓動線程
button1.Enabled=false;
}
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
try
{
tlTcpListen.Stop(); //關閉偵聽(tīng)
nsStream.Close();
srRead.Close();//釋放(fàng)資(zī)源
thThreadRead.Abort();//中(zhōng)止線程
}
catch{}
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
TCP協議的發送端
using System.Net.Sockets; //使用到TcpListen類
using System.Threading; //使用到線程
using System.IO; //使用到StreamWriter類
using System.Net; //使用IPAddress類、IPHostEntry類等
private StreamWriter swWriter; //用以向網絡基礎數據流傳送數據
private NetworkStream nsStream; //創建發送數據的網絡基礎數據流
private TcpClient tcpClient;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.StatusBar statusBar1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2; //通過它實現向遠程主機提出TCP連接申請
private bool tcpConnect = false; //定義标識符,用以表示TCP連接是否建立
//連接
private void button1_Click(object sender, System.EventArgs e)
{
IPAddress ipRemote ;
try
{
ipRemote = IPAddress.Parse ( textBox1.Text ) ;
}
catch //判斷給定的IP地址的合法性
{
MessageBox.Show ( "輸入的IP地址不合法!" , "錯誤提示!" ) ;
return ;
}
IPHostEntry ipHost ;
try
{
ipHost = Dns.Resolve ( textBox1.Text ) ;
}
catch //判斷IP地址對應主機是否在線
{
MessageBox.Show ("遠程主機不在線!" , "錯誤提示!" ) ;
return ;
}
string sHostName = ipHost.HostName ;
try
{
TcpClient tcpClient = new TcpClient(sHostName,8000);//對遠程主機的8000端口提出TCP連接申請
nsStream = tcpClient.GetStream();//通過申請,并獲取傳送數據的網絡基礎數據流
swWriter = new StreamWriter(nsStream);//使用獲取的網絡基礎數據流來初始化StreamWriter實例
button1.Enabled = false ;
button2.Enabled = true ;
tcpConnect = true ;
statusBar1.Text = "已經連接!" ;
}
catch
{
MessageBox.Show ( "無法和遠程主機8000端口建立連接!" , "錯誤提示!" ) ;
return ;
}
}
//發送
private void button2_Click(object sender, System.EventArgs e)
{
if (textBox2.Text !="")
{
swWriter.WriteLine(textBox2.Text);//刷新當前數據流中(zhōng)的數據
swWriter.Flush();
}
else
{
MessageBox.Show("發送信息不能爲空!","錯誤提示!");
}
}
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
if ( tcpConnect )
{
swWriter.WriteLine ( "STOP" ) ; //發送控制碼
swWriter.Flush (); //刷新當前數據流中(zhōng)的數據
nsStream.Close (); //清除資(zī)源
swWriter.Close ();
}
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
異步套接字
BeginAccept
Public IAsyncResult BeginAccept{AsyncCallback callback,object state}
AsyncCallback異步回調方法 object state自定義對象, 返回IasyncResult
Using System;
Namespace mySocket
{
Public class Stateobject
{
Public StateObject(){構造函數邏輯}
}
}à>
Using System;
Using System.Net;
Using System.Net.Sockets;
Using System.Threading;
Using System.Text;
Namespace mysocket
{
Public Class StateObject
{
Public Socket worksocket=null;
Public const int buffersize=1024;
Public byte[] buffer=new byte[buffersize];
Public StringBuilder sb=new StringBuilder();
Public StateObject()
{}
}
}
實現主機綁定和端口監聽(tīng):
Private IPAddress myIP=IPAddress.Parse(“127.0.0.1”);
Private IPEndPoint MyServer;
Private Socket mySocket;
Private Socket Handler;
Private Static ManualResetEvent myreset =new ManualResetEvent(false);
Try
{
IPHostEntry myhost=new IPHostEntry();
Myhost=dns.gethostbyName(“”);
String IPString =myhost.Addresslist[0].tostring();
Myip=IPAddress.Parse(IPString);
}
Catch{MessageBox.Show(“您輸入的IP地址格式不正确,重新輸入!”);}
Try
{
MyServer=new IPEndPoint(myIP,Int32.Parse(“Port”));
Mysocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,Protocol.Tcp);
Mysocket.Bind(Myserver);
Mysocket.Listen(50);
Thread thread=new Thread(new ThreadStart(target));
Thread.Start();
}
Catch(Exception ee){}
線程target
Private void target()
{
While(true)
{
myReset.Reset();
mysocket.BeginAccept(new AsyncCallBack(AcceptCallback),mysocket);
myReset.WaitOne();
}
}
異步回調方法AcceptCallBack
Private void AcceptCallback(IAsyncResault ar)
{
myReset.Set();
Socket Listener=(Socket)ar.AsyncState;
Handler=Listener.EndAccept(ar);
StateObject state=new StateObject();
State.workSocket=handler;
Try
{
Byte[] byteData=System.Text.Encoding.BigEndianUnicode.GetBytes(“通話(huà)!”+”\n\r”);
Handler.BeginSend(byuteData,0,byteData.Length,0,new AsyncCallback(SendCallback),handler);
}
Catch(Exception ee)
{MessageBox.Show(ee.Message);}
Thread thread=new Thread(new ThreadStart(begreceive));
Thread.Start();
}
多線程:
每個窗體(tǐ)自己都在不同的線程上面運行,如果需要在窗體(tǐ)之間交互,需要在線程之間交互
當線程sleep,系統就使之退出執行隊列,當睡眠結束,系統産生(shēng)時鍾中(zhōng)斷,使該線程回到執行隊列中(zhōng),回複線程的執行。
如果父線程先于子線程結束,那麽子線程在父線程結束的時候被迫結束,Thread.Join()是父線程等待子線程結束。Abort帶來的是不可回複的終止線程
起始線程爲主線程,前台線程全部結束,則主線程可以終止,後台線程無條件終止。
前台線程不妨礙程序終止,一(yī)旦進程的所有前台線程終止,則clr調用任意一(yī)個還存活的後台線程的abort來徹底終止進程。
挂起,睡眠(阻塞,暫停)
Thread.Suspend不會使線程立即停止執行,直到線程到達安全點的時候它才可以将該線程挂起,如果線程尚未運行或這已經停止,則不能被挂起,調用thread.resume使另一(yī)個線程跳出挂起狀态,繼續執行。
一(yī)個線程不能對另一(yī)個線程調用sleep,但是可以suspend。
Lock可以把一(yī)段代碼定義爲互斥段critical section 互斥段在一(yī)個時刻内隻允許一(yī)個線程進入執行,其他線程必須等待
多線程公用對象,不應該使用lock,monitor提供了線程共享資(zī)源的方案,monitor可以鎖定一(yī)個對象,線程隻有得到鎖才可以對該對象進行操作
一(yī)個進程開(kāi)始至少有一(yī)個主線程。系統加載程序時創建主執行線程
消息隊列與線程相關
一(yī)開(kāi)始創建線程就産生(shēng)消息隊列了,一(yī)個線程可以創建多個窗體(tǐ),而發給這些窗體(tǐ)的消息都同意發送到同一(yī)個消息隊列中(zhōng)了,消息結構中(zhōng)有msg.hwnd指出該條消息與哪個窗體(tǐ)相關
DispatchMessage()函數依照這個保證消息分(fēn)派處理自動化而且不會出錯。
線程控制方法:
Start線程開(kāi)始運行
Sleep 是線程暫停一(yī)段指定時間
Suspend 線程在到達安全點後暫停
Abort 線程到達安全點後停止
Resume 重新啓動挂起的線程
Join 當前線程等待其他線程運行結束。如果使用超時值,且線程在分(fēn)配的時間内結束,方法返回true
安全點:代碼中(zhōng)的某些位置,這些位置公共語言運行時可以安全的執行自動垃圾回收,即釋放(fàng)未使用的變量并回收内存,調用線程的abort和suspend方法時,公共語言運行時将分(fēn)析代碼并确定線程停止運行的适當位置。
Socket支持下(xià)的網上點對點的通信
服務端實現監聽(tīng)連接,客戶端實現發送連接請求,建立連接後進行發送和接收數據的功能
服務器端建立一(yī)個socket,設置好本機的ip和監聽(tīng)的端口與socket進行綁定,開(kāi)始監聽(tīng)連接請求,當接收到連接請求後,發送确認,同客戶端建立連接,開(kāi)始與客戶端進行通信。
客戶端建立一(yī)個socket,設置好服務器端的IP和提供服務的端口,發出連接請求,接收到服務的确認後,盡力連接,開(kāi)始與服務器進行通信。
服務器端和客戶端的連接及它們之間的數據傳送均采用同步方式。
Socket
Socket是tcp\ip網絡協議接口。内部定義了許多的函數和例程。可以看成是網絡通信的一(yī)個端點。在網絡通信中(zhōng)需要兩個主機或兩個進程。通過網絡傳遞數據,程序在網絡對話(huà)的每一(yī)端需要一(yī)個socket。
Tcp/IP傳輸層使用協議端口将數據傳送給一(yī)個主機的特定應用程序,協議端口是一(yī)個應用程序的進程地址。傳輸層模塊的網絡軟件模塊要于另一(yī)個程序通信,它将使用協議端口,socket是運行在傳輸層的api,使用socket建立連接發送數據要指定一(yī)個端口給它。
Socket:
Stream Socket流套接字 Socket提供雙向、有序、無重複的數據流服務,出溜大(dà)量的網絡數據。
Dgram socket數據包套接字 支持雙向數據流,不保證傳輸的可靠性、有序、無重複。
Row socket 原始套接字 訪問底層協議
建立socket 用C#
命名空間:using System.Net;using System.Net.Socket;
構造新的socket對象:socket原型:
Public socket (AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)
AddressFamily 用來指定socket解析地址的尋址方案。InterNetwork标示需要ip版本4的地址,InterNetworkV6需要ip版本6的地址
SocketType參數指定socket類型Raw支持基礎傳輸協議訪問,Stream支持可靠,雙向,基于連接的數據流。
ProtocolType表示socket支持的網絡協議
定義主機對象:
IPEndPoint類:IPEndPoint構造方法 位置:System.Net
原型:1) public IPEndPoint(IPAddress address,int port) 2)public IPEndPoint(long address,int port) 參數1整型int64如123456,參數2端口int32
主機解析:
利用DNS服務器解析主機,使用Dns.Resolve方法
原型:public static IPHostEntry Resolve(string hostname) 參數:待解析的主機名稱,返回IPHostEntry類值,IPHostEntry爲Internet主機地址信息提供容器,該容器提供存有IP地址列表,主機名稱等。
Dns.GetHostByName獲取本地主機名稱
原型:public static IPHostEntry GetHostByName(string hostname)
GetHostByAddress
原型:1)public static IPHostEntry GetHostByAddress(IPAddress address) 參數:IP地址 2)public static IPHostEntry GetHostByAddress(string address) IP地址格式化字符串
端口綁定和監聽(tīng):
同步套接字服務器主機的綁定和端口監聽(tīng)
Socket類的Bind(綁定主機),Listen(監聽(tīng)端口),Accept(接收客戶端的連接請求)
Bind:原型:public void Bind(EndPoint LocalEP)參數爲主機對象 IPEndPoint
Listen:原型:public void Listen(int backlog) 參數整型數值,挂起隊列最大(dà)值
accept:原型:public socket accept() 返回爲套接字對象
演示程序:
IPAddress myip=IPAddress.Parse(“127.0.0.1”);
IPEndPoint myserver=new IPEndPoint(myip,2020);
Socket sock=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Sock.Bind(myserver);
Sock.Listen(50);
Socket bbb=sock.Accept();
發送數據:方法1:socket類的send方法二:NetworkStream類Write
send原型:public int Send(byte[] buffer) 字節數組
public int Send(byte[],SocketFlags)原型2說明,SocketFlags成員(yuán)列表:DontRoute(不使用路由表發送),MaxIOVectorLength(爲發送和接收數據的wsabuf結構數量提供标準值)None 不對次調用使用标志(zhì)) OutOfBand(消息的部分(fēn)發送或接收)Partial(消息的部分(fēn)發送或接收) Peek(查看傳入的消息)
原型三:public int Send(byte[],int,SocketFlags) 參數二要發送的字節數
原型四:public int Send(byte[],int,int,SocketFlags) 參數二爲Byte[]中(zhōng)開(kāi)始發送的位置
演示:
Socket bbb=sock.Accept();
Byte[] bytes=new Byte[64];
string send="aaaaaaaaaaaa";
bytes=System.Text.Encoding.BigEndianUnicode.GetBytes(send.ToCharArray());
bbb.Send(bytes,bytes.length,0);//将byte數組全部發送
NetWordStream類的Write方法發送數據
原型:public override void write(byte[] buffer,int offset,int size) 字節數組,開(kāi)始字節位置,總字節數
Socket bbb=sock.Accept();
NetWorkStream stre=new NewWorkStream(bbb);
Byte[] ccc=new Byte[512];
string sendmessage="aaaaaaaaaaaaaa";
ccc=System.Text.Encoding.BigEndianUnicode.GetBytes(sendmessage);
stre.Write(ccc,0,ccc.length);
接收數據:Socket類Receive或NetworkStream類Read
Socket類Receive方法
原型:public int Receive(byte[] buffer)
2)public int Receive(byte[],SocketFlags)
3)public int Receive(byte[],int,SocketFlags)
4)public int Receive(byte[],int,int,SocketFlags)
.....
Socket bbb=sock.Accept();
........
Byte[] ccc=new Byte[512];
bbb.Receive(ccc,ccc.Length,0);
string rece=System.Text.Encoding.BigEndianUnicode.GetString(ccc);
richTextBox1.AppendText(rece+"\r\n");
NetworkStream類的Read方法接收數據
public override int Read(int byte[] buffer,int offset,int size)
演示:bbb=sock.Accept();
.......
NetworkStream stre=new NetworkStream(bbb);
Byte[] ccc=new Byte[512];
stre.Read(ccc,0,ccc.Length);
string readMessage=System.Text.Encoding.BigEndianUnicode.GetString(ccc);
線程
線程創建:System.Threading空間下(xià)的Thread類的構造方法:
原型:public Thread(ThreadStart start) ThreadStart類型值
Thread thread=new Thread(new ThreadStart(accp));
Private void accp(){}//使用線程操作
線程啓動
Thread thread=new Thread(new ThreadStart(accp));
線程暫停與重新啓動
啓動線程使用Thread.Sleep是當前線程阻塞一(yī)段時間Thread.Sleep(Timeout.Infinite)是線程休眠,直到被調用Thread.Interrrupt的另一(yī)個線程中(zhōng)斷或被Thread.Abort中(zhōng)止。
一(yī)個線程不能對另一(yī)個調用Sleep,可以使用Thread.Suspend來暫停線程,當線程對自身調用Thread.Suspend将阻塞,直到該線程被另一(yī)個線程繼續,當一(yī)個線程對另一(yī)個調用,該調用就成爲使另一(yī)個線程暫停的非阻塞調用。調用Thread.Resume使另一(yī)個線程跳出挂起狀态并使該線程繼續執行,而與調用Thread.Suspend的次數無關
線程休眠:Thread.Sleep(10000);
線程挂起:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Suspend();
重新啓動:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Suspend();
Thread.Resume();
阻塞線程的方法:thread.Join使用一(yī)個線程等待另一(yī)個線程停止
Thread.Join
Public void Join();
Public void Join(int millisecondsTimeout);毫秒
Public bool Join(TimeSpan timeout);時間間隔類型值
實例:Thread thread=new Thread(new ThreadStart(accp));
Thread.start();
Thread.Join(10000);
線程銷毀:
Thread.Abort,Thread.Interrupt
Abort方法引發ThreadAbortException,開(kāi)始中(zhōng)止此線程的過程,是一(yī)個可以由應用程序代碼捕獲的特殊異常,ResetAbort可以取消Abort請求,可以組織ThreadAbortException終止此線程,線程不一(yī)定會立即終止,根本不終止。
對尚未啓動的線程調用Abort,則當調用Start時該線程将終止。對已經挂起的線程調用Abort,則該線程将繼續,然後終止。對阻塞或正在休眠的線程調用Abort,則該線程被中(zhōng)斷,然後終止。
Thread類的Abort方法:
Public void Abort()
Public void Abort(object stateinfo);
演示:
Thread thread=new Thread(new ThreadStart(accp));
Thread.Start();
Thread.Abort();
Thread.Join(10000);
Socket編程原理:
Unix的i/o命令集,模式爲開(kāi)-讀/寫-關 open write/read close
用戶進程進行i/o操作
用戶進程調用打開(kāi)命令,獲取文件或設備的使用權,并返回描述文件或設備的整數,以描述用戶打開(kāi)的進程,該進程進行讀寫操作,傳輸數據,操作完成,進程關閉,通知(zhī)os對哪個對象進行了使用。
Unix網絡應用編程:BSD的套接字socket,unix的System V 的TLI。
套接字編程的基本概念:
網間進程通信:源于單機系統,每個進程在自己的地址範圍内進行運行,保證互相不幹擾且協調工(gōng)作。操作系統爲進程之間的通信提供設施:
Unix BSD 管道pipe,命名管道named pipe軟中(zhōng)斷信号signal
Unix System V 消息message 共享存儲區 shared memory 信号量semaphore
以上僅限于本機進程之間通信。
端口:網絡上可以被命名和尋址的通信端口,是操作系統可以分(fēn)配的一(yī)種資(zī)源,網絡通信的最終地址不是主機地址,是可以描述進程的摸中(zhōng)标識符。TCP/IP提出協議端口porotocol port端口,表示通信進程。
進程通過os調用綁定連接端口,而在傳輸層傳輸給該端口的數據傳入進程中(zhōng)處理,同樣在進程的數據需要傳給傳輸層也是通過綁定端口實現。進程對端口的操作相當于對os中(zhōng)的i/o文件進行操作,每一(yī)個端口也對應着一(yī)個端口号,tcp/ip協議分(fēn)爲tcp和udp,雖然有相同port number的端口,但是互相也不沖突。 端口号的分(fēn)配有全局分(fēn)配,本地分(fēn)配(動态分(fēn)配),當進程需要訪問傳輸層,os分(fēn)配給進程一(yī)個端口号。全局分(fēn)配,就是os固定分(fēn)配的端口,标準的服務器都有固定的全局公認的端口号提供給服務。小(xiǎo)于256的可以作爲保留端口。
地址:網絡通信中(zhōng)的兩台機器,可以不再同一(yī)個網絡,可能間隔(網關,網橋,路由器等),所以可以分(fēn)爲三層尋址
機器在不同的網絡則有該網絡的特定id
同一(yī)個網絡中(zhōng)的機器應該有唯一(yī)的機器id
一(yī)台機器内的進程應該有自己的唯一(yī)id
通常主機地址=網絡ID+主機ID tcp/ip中(zhōng)使用16位端口号來表示進程。
網絡字節順序,高價先存,tcp和udp都使用16或32整數位的高價存儲,在協議的頭文件中(zhōng)。
半相關:在網絡中(zhōng)一(yī)個進程爲協議+本地地址+端口号=三元組,也叫半相關,表示半部分(fēn)。
全相關:兩台機器之間通信需要使用相同協議
協議+本地地址+本地端口号+遠程地址+遠程端口号 五元組 全相關。
順序:兩個連續的報文在網絡中(zhōng)可能不會通過相同的路徑到達,所以接收的順序會和發送的順序不一(yī)緻。順序是接收順序與發送順序一(yī)緻。Tcp/ip提供該功能。
差錯控制:檢查數據差錯:檢查和CheckSum機制 檢查連接差錯:雙方确認應答機制。
流控制:雙方傳輸數據過程中(zhōng),保證數據傳輸速率的機制,保證數據不丢失。
字節流:把傳輸中(zhōng)的報文當作一(yī)個字節序列,不提供任何數據邊界。
全雙工(gōng)/半雙工(gōng):兩個方向發送或一(yī)個方向發送
緩存/帶外(wài)數據:字節流服務中(zhōng),沒有報文邊界,可以同一(yī)時刻讀取任意長度的數據。爲保證傳輸正确或流協議控制,需要使用緩存,交互型的應用程序禁用緩存。
數據傳送中(zhōng),希望不通過常規傳輸方式傳送給用戶以便及時處理的某一(yī)類信息(unix系統的中(zhōng)斷鍵delete,Control-c)、終端流控制符Control-s、Control-q)爲帶外(wài)數據。
客戶/服務器模式主動請求方式:
1. 打開(kāi)通信通道,通知(zhī)本地主機,在某一(yī)個公認地址上接收客戶請求
2. 等待客戶請求到達端口
3. 接收到重複服務請求,處理請求發送應答信号。接收到并發服務請求。要激活一(yī)個新進程處理客戶請求,unix系統fork、exec,新進程處理客戶請求,不需要對其他請求作出應答,服務完成後,關閉此進程與客戶的通信鏈路。終止
4. 返回第二步,等待另一(yī)個客戶請求。
5. 關閉服務端
客戶方:
1. 打開(kāi)一(yī)通信通道,并連接到服務器所在主機的特定端口。
2. 向服務器發送服務請求報文,等待并接收應答;繼續提出請求…….
3. 請求結束以後關閉通信通道并終止。
:
1. 客戶與服務器進程的作用非對稱,編碼不同
2. 服務進程先于客戶請求而啓動,系統運行,服務進程一(yī)緻存在,直到正常退出或強迫退出
套接字類型:
TCP/IP的socket
Sock_stream可靠的面對連接數據傳輸,無差錯、無重複發送,安照順序發送接收,内設流量控制,避免數據流超限,數據爲字節流,無長度限制,ftp流套接字。
Sock_DGRAM 無連接的服務,數據包以獨立包的形式發送,不提供無措保證,數據可能丢失重複,發送接收的順序混亂,網絡文件系統nfs使用數據報式套接字。
Sock_Ram 接口允許較底層協議,IP,ICMP直接訪問,檢查新的協議實現或訪問現有服務中(zhōng)配置的新設備。
服務端:
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
Thread mythread ;
Socket socket;
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
try
{
socket.Close();//釋放(fàng)資(zī)源
mythread.Abort ( ) ;//中(zhōng)止線程
}
catch{ }
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
public static IPAddress GetServerIP()
{
IPHostEntry ieh=Dns.GetHostByName(Dns.GetHostName());
return ieh.AddressList[0];
}
private void BeginListen()
{
IPAddress ServerIp=GetServerIP();
IPEndPoint iep=new IPEndPoint(ServerIp,8000);
socket=new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
byte[] byteMessage=new byte[100];
this.label1.Text=iep.ToString();
socket.Bind(iep);
// do
while(true)
{
try
{
socket.Listen(5);
Socket newSocket=socket.Accept();
newSocket.Receive(byteMessage);
string sTime = DateTime.Now.ToShortTimeString ( ) ;
string msg=sTime+":"+"Message from:";
msg+=newSocket.RemoteEndPoint.ToString()+Encoding.Default.GetString(byteMessage);
this.listBox1.Items.Add(msg);
}
catch(SocketException ex)
{
this.label1.Text+=ex.ToString();
}
}
// while(byteMessage!=null);
}
//開(kāi)始監聽(tīng)
private void button1_Click(object sender, System.EventArgs e)
{
try
{
mythread = new Thread(new ThreadStart(BeginListen));
mythread.Start();
}
catch(System.Exception er)
{
MessageBox.Show(er.Message,"完成",MessageBoxButtons.OK,MessageBoxIcon.Stop);
}
}
客戶端:
using System.Net;
using System.Net.Sockets;
using System.Text;
private void button1_Click(object sender, System.EventArgs e)
{
BeginSend();
}
private void BeginSend()
{
string ip=this.txtip.Text;
string port=this.txtport.Text;
IPAddress serverIp=IPAddress.Parse(ip);
int serverPort=Convert.ToInt32(port);
IPEndPoint iep=new IPEndPoint(serverIp,serverPort);
byte[] byteMessage;
// do
// {
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
socket.Connect(iep);
byteMessage=Encoding.ASCII.GetBytes(textBox1.Text);
socket.Send(byteMessage);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
// }
// while(byteMessage!=null);
}
基于TCP協議的發送和接收端
TCP協議的接收端
using System.Net.Sockets ; //使用到TcpListen類
using System.Threading ; //使用到線程
using System.IO ; //使用到StreamReader類
int port = 8000; //定義偵聽(tīng)端口号
private Thread thThreadRead; //創建線程,用以偵聽(tīng)端口号,接收信息
private TcpListener tlTcpListen; //偵聽(tīng)端口号
private bool blistener = true; //設定标示位,判斷偵聽(tīng)狀态
private NetworkStream nsStream; //創建接收的基本數據流
private StreamReader srRead;
private System.Windows.Forms.StatusBar statusBar1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1; //從網絡基礎數據流中(zhōng)讀取數據
private TcpClient tcClient ;
private void Listen ( )
{
try
{
tlTcpListen = new TcpListener ( port ) ; //以8000端口号來初始化TcpListener實例
tlTcpListen.Start ( ) ; //開(kāi)始監聽(tīng)
statusBar1.Text = "正在監聽(tīng)..." ;
tcClient = tlTcpListen.AcceptTcpClient ( ) ; //通過TCP連接請求
nsStream = tcClient.GetStream ( ) ; //獲取用以發送、接收數據的網絡基礎數據流
srRead=new StreamReader(nsStream);//以得到的網絡基礎數據流來初始化StreamReader實例
statusBar1.Text = "已經連接!";
while( blistener ) //循環偵聽(tīng)
{
string sMessage = srRead.ReadLine();//從網絡基礎數據流中(zhōng)讀取一(yī)行數據
if ( sMessage == "STOP" ) //判斷是否爲斷開(kāi)TCP連接控制碼
{
tlTcpListen.Stop(); //關閉偵聽(tīng)
nsStream.Close(); //釋放(fàng)資(zī)源
srRead.Close();
statusBar1.Text = "連接已經關閉!" ;
thThreadRead.Abort(); //中(zhōng)止線程
return;
}
string sTime = DateTime.Now.ToShortTimeString ( ) ; //獲取接收數據時的時間
listBox1.Items.Add ( sTime + " " + sMessage ) ;
}
}
catch ( System.Security.SecurityException )
{
MessageBox.Show ( "偵聽(tīng)失敗!" , "錯誤" ) ;
}
}
//開(kāi)始監聽(tīng)
private void button1_Click(object sender, System.EventArgs e)
{
thThreadRead = new Thread ( new ThreadStart ( Listen ) );
thThreadRead.Start();//啓動線程
button1.Enabled=false;
}
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
try
{
tlTcpListen.Stop(); //關閉偵聽(tīng)
nsStream.Close();
srRead.Close();//釋放(fàng)資(zī)源
thThreadRead.Abort();//中(zhōng)止線程
}
catch{}
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
TCP協議的發送端
using System.Net.Sockets; //使用到TcpListen類
using System.Threading; //使用到線程
using System.IO; //使用到StreamWriter類
using System.Net; //使用IPAddress類、IPHostEntry類等
private StreamWriter swWriter; //用以向網絡基礎數據流傳送數據
private NetworkStream nsStream; //創建發送數據的網絡基礎數據流
private TcpClient tcpClient;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.StatusBar statusBar1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2; //通過它實現向遠程主機提出TCP連接申請
private bool tcpConnect = false; //定義标識符,用以表示TCP連接是否建立
//連接
private void button1_Click(object sender, System.EventArgs e)
{
IPAddress ipRemote ;
try
{
ipRemote = IPAddress.Parse ( textBox1.Text ) ;
}
catch //判斷給定的IP地址的合法性
{
MessageBox.Show ( "輸入的IP地址不合法!" , "錯誤提示!" ) ;
return ;
}
IPHostEntry ipHost ;
try
{
ipHost = Dns.Resolve ( textBox1.Text ) ;
}
catch //判斷IP地址對應主機是否在線
{
MessageBox.Show ("遠程主機不在線!" , "錯誤提示!" ) ;
return ;
}
string sHostName = ipHost.HostName ;
try
{
TcpClient tcpClient = new TcpClient(sHostName,8000);//對遠程主機的8000端口提出TCP連接申請
nsStream = tcpClient.GetStream();//通過申請,并獲取傳送數據的網絡基礎數據流
swWriter = new StreamWriter(nsStream);//使用獲取的網絡基礎數據流來初始化StreamWriter實例
button1.Enabled = false ;
button2.Enabled = true ;
tcpConnect = true ;
statusBar1.Text = "已經連接!" ;
}
catch
{
MessageBox.Show ( "無法和遠程主機8000端口建立連接!" , "錯誤提示!" ) ;
return ;
}
}
//發送
private void button2_Click(object sender, System.EventArgs e)
{
if (textBox2.Text !="")
{
swWriter.WriteLine(textBox2.Text);//刷新當前數據流中(zhōng)的數據
swWriter.Flush();
}
else
{
MessageBox.Show("發送信息不能爲空!","錯誤提示!");
}
}
// 清理所有正在使用的資(zī)源。
protected override void Dispose( bool disposing )
{
if ( tcpConnect )
{
swWriter.WriteLine ( "STOP" ) ; //發送控制碼
swWriter.Flush (); //刷新當前數據流中(zhōng)的數據
nsStream.Close (); //清除資(zī)源
swWriter.Close ();
}
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
異步套接字
BeginAccept
Public IAsyncResult BeginAccept{AsyncCallback callback,object state}
AsyncCallback異步回調方法 object state自定義對象, 返回IasyncResult
Using System;
Namespace mySocket
{
Public class Stateobject
{
Public StateObject(){構造函數邏輯}
}
}à>
Using System;
Using System.Net;
Using System.Net.Sockets;
Using System.Threading;
Using System.Text;
Namespace mysocket
{
Public Class StateObject
{
Public Socket worksocket=null;
Public const int buffersize=1024;
Public byte[] buffer=new byte[buffersize];
Public StringBuilder sb=new StringBuilder();
Public StateObject()
{}
}
}
實現主機綁定和端口監聽(tīng):
Private IPAddress myIP=IPAddress.Parse(“127.0.0.1”);
Private IPEndPoint MyServer;
Private Socket mySocket;
Private Socket Handler;
Private Static ManualResetEvent myreset =new ManualResetEvent(false);
Try
{
IPHostEntry myhost=new IPHostEntry();
Myhost=dns.gethostbyName(“”);
String IPString =myhost.Addresslist[0].tostring();
Myip=IPAddress.Parse(IPString);
}
Catch{MessageBox.Show(“您輸入的IP地址格式不正确,重新輸入!”);}
Try
{
MyServer=new IPEndPoint(myIP,Int32.Parse(“Port”));
Mysocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,Protocol.Tcp);
Mysocket.Bind(Myserver);
Mysocket.Listen(50);
Thread thread=new Thread(new ThreadStart(target));
Thread.Start();
}
Catch(Exception ee){}
線程target
Private void target()
{
While(true)
{
myReset.Reset();
mysocket.BeginAccept(new AsyncCallBack(AcceptCallback),mysocket);
myReset.WaitOne();
}
}
異步回調方法AcceptCallBack
Private void AcceptCallback(IAsyncResault ar)
{
myReset.Set();
Socket Listener=(Socket)ar.AsyncState;
Handler=Listener.EndAccept(ar);
StateObject state=new StateObject();
State.workSocket=handler;
Try
{
Byte[] byteData=System.Text.Encoding.BigEndianUnicode.GetBytes(“通話(huà)!”+”\n\r”);
Handler.BeginSend(byuteData,0,byteData.Length,0,new AsyncCallback(SendCallback),handler);
}
Catch(Exception ee)
{MessageBox.Show(ee.Message);}
Thread thread=new Thread(new ThreadStart(begreceive));
Thread.Start();
}
多線程:
每個窗體(tǐ)自己都在不同的線程上面運行,如果需要在窗體(tǐ)之間交互,需要在線程之間交互
當線程sleep,系統就使之退出執行隊列,當睡眠結束,系統産生(shēng)時鍾中(zhōng)斷,使該線程回到執行隊列中(zhōng),回複線程的執行。
如果父線程先于子線程結束,那麽子線程在父線程結束的時候被迫結束,Thread.Join()是父線程等待子線程結束。Abort帶來的是不可回複的終止線程
起始線程爲主線程,前台線程全部結束,則主線程可以終止,後台線程無條件終止。
前台線程不妨礙程序終止,一(yī)旦進程的所有前台線程終止,則clr調用任意一(yī)個還存活的後台線程的abort來徹底終止進程。
挂起,睡眠(阻塞,暫停)
Thread.Suspend不會使線程立即停止執行,直到線程到達安全點的時候它才可以将該線程挂起,如果線程尚未運行或這已經停止,則不能被挂起,調用thread.resume使另一(yī)個線程跳出挂起狀态,繼續執行。
一(yī)個線程不能對另一(yī)個線程調用sleep,但是可以suspend。
Lock可以把一(yī)段代碼定義爲互斥段critical section 互斥段在一(yī)個時刻内隻允許一(yī)個線程進入執行,其他線程必須等待
多線程公用對象,不應該使用lock,monitor提供了線程共享資(zī)源的方案,monitor可以鎖定一(yī)個對象,線程隻有得到鎖才可以對該對象進行操作
一(yī)個進程開(kāi)始至少有一(yī)個主線程。系統加載程序時創建主執行線程
消息隊列與線程相關
一(yī)開(kāi)始創建線程就産生(shēng)消息隊列了,一(yī)個線程可以創建多個窗體(tǐ),而發給這些窗體(tǐ)的消息都同意發送到同一(yī)個消息隊列中(zhōng)了,消息結構中(zhōng)有msg.hwnd指出該條消息與哪個窗體(tǐ)相關
DispatchMessage()函數依照這個保證消息分(fēn)派處理自動化而且不會出錯。
線程控制方法:
Start線程開(kāi)始運行
Sleep 是線程暫停一(yī)段指定時間
Suspend 線程在到達安全點後暫停
Abort 線程到達安全點後停止
Resume 重新啓動挂起的線程
Join 當前線程等待其他線程運行結束。如果使用超時值,且線程在分(fēn)配的時間内結束,方法返回true
安全點:代碼中(zhōng)的某些位置,這些位置公共語言運行時可以安全的執行自動垃圾回收,即釋放(fàng)未使用的變量并回收内存,調用線程的abort和suspend方法時,公共語言運行時将分(fēn)析代碼并确定線程停止運行的适當位置。