同步套接字通信
socket支持下的網(wǎng)上點對點的通信
服務(wù)端實現(xiàn)監(jiān)聽連接,客戶端實現(xiàn)發(fā)送連接請求,建立連接后進行發(fā)送和接收數(shù)據(jù)的功能
服務(wù)器端建立一個socket,設(shè)置好本機的ip和監(jiān)聽的端口與socket進行綁定,開始監(jiān)聽連接請求,當(dāng)接收到連接請求后,發(fā)送確認(rèn),同客戶端建立連接,開始與客戶端進行通信。
客戶端建立一個socket,設(shè)置好服務(wù)器端的ip和提供服務(wù)的端口,發(fā)出連接請求,接收到服務(wù)的確認(rèn)后,盡力連接,開始與服務(wù)器進行通信。
服務(wù)器端和客戶端的連接及它們之間的數(shù)據(jù)傳送均采用同步方式。
socket
socket是tcp/ip網(wǎng)絡(luò)協(xié)議接口。內(nèi)部定義了許多的函數(shù)和例程。可以看成是網(wǎng)絡(luò)通信的一個端點。在網(wǎng)絡(luò)通信中需要兩個主機或兩個進程。通過網(wǎng)絡(luò)傳遞數(shù)據(jù),程序在網(wǎng)絡(luò)對話的每一端需要一個socket。
tcp/ip傳輸層使用協(xié)議端口將數(shù)據(jù)傳送給一個主機的特定應(yīng)用程序,協(xié)議端口是一個應(yīng)用程序的進程地址。傳輸層模塊的網(wǎng)絡(luò)軟件模塊要于另一個程序通信,它將使用協(xié)議端口,socket是運行在傳輸層的api,使用socket建立連接發(fā)送數(shù)據(jù)要指定一個端口給它。
socket:
stream socket流套接字 socket提供雙向、有序、無重復(fù)的數(shù)據(jù)流服務(wù),出溜大量的網(wǎng)絡(luò)數(shù)據(jù)。
dgram socket數(shù)據(jù)包套接字 支持雙向數(shù)據(jù)流,不保證傳輸?shù)目煽啃浴⒂行颉o重復(fù)。
row socket 原始套接字 訪問底層協(xié)議
建立socket 用c#
命名空間:using system.net;using system.net.socket;
構(gòu)造新的socket對象:socket原型:
public socket (addressfamily addressfamily,sockettype sockettype,protocoltype protocoltype)
addressfamily 用來指定socket解析地址的尋址方案。internetwork標(biāo)示需要ip版本4的地址,internetworkv6需要ip版本6的地址
sockettype參數(shù)指定socket類型raw支持基礎(chǔ)傳輸協(xié)議訪問,stream支持可靠,雙向,基于連接的數(shù)據(jù)流。
protocoltype表示socket支持的網(wǎng)絡(luò)協(xié)議
定義主機對象:
ipendpoint類:ipendpoint構(gòu)造方法 位置:system.net
原型:1) public ipendpoint(ipaddress address,int port) 2)public ipendpoint(long address,int port) 參數(shù)1整型int64如123456,參數(shù)2端口int32
主機解析:
利用dns服務(wù)器解析主機,使用dns.resolve方法
原型:public static iphostentry resolve(string hostname) 參數(shù):待解析的主機名稱,返回iphostentry類值,iphostentry為internet主機地址信息提供容器,該容器提供存有ip地址列表,主機名稱等。
dns.gethostbyname獲取本地主機名稱
原型:public static iphostentry gethostbyname(string hostname)
gethostbyaddress
原型:1)public static iphostentry gethostbyaddress(ipaddress address) 參數(shù):ip地址 2)public static iphostentry gethostbyaddress(string address) ip地址格式化字符串
端口綁定和監(jiān)聽:
同步套接字服務(wù)器主機的綁定和端口監(jiān)聽
socket類的bind(綁定主機),listen(監(jiān)聽端口),accept(接收客戶端的連接請求)
bind:原型:public void bind(endpoint localep)參數(shù)為主機對象 ipendpoint
listen:原型:public void listen(int backlog) 參數(shù)整型數(shù)值,掛起隊列最大值
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();
發(fā)送數(shù)據(jù):方法1:socket類的send方法二:networkstream類write
send原型:public int send(byte[] buffer) 字節(jié)數(shù)組
public int send(byte[],socketflags)原型2說明,socketflags成員列表:dontroute(不使用路由表發(fā)送),maxiovectorlength(為發(fā)送和接收數(shù)據(jù)的wsabuf結(jié)構(gòu)數(shù)量提供標(biāo)準(zhǔn)值)none 不對次調(diào)用使用標(biāo)志) outofband(消息的部分發(fā)送或接收)partial(消息的部分發(fā)送或接收) peek(查看傳入的消息)
原型三:public int send(byte[],int,socketflags) 參數(shù)二要發(fā)送的字節(jié)數(shù)
原型四:public int send(byte[],int,int,socketflags) 參數(shù)二為byte[]中開始發(fā)送的位置
演示:
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數(shù)組全部發(fā)送
networdstream類的write方法發(fā)送數(shù)據(jù)
原型:public override void write(byte[] buffer,int offset,int size) 字節(jié)數(shù)組,開始字節(jié)位置,總字節(jié)數(shù)
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);
接收數(shù)據(jù):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方法接收數(shù)據(jù)
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);
線程
線程創(chuàng)建:system.threading空間下的thread類的構(gòu)造方法:
原型:public thread(threadstart start) threadstart類型值
thread thread=new thread(new threadstart(accp));
private void accp(){}//使用線程操作
線程啟動
thread thread=new thread(new threadstart(accp));
線程暫停與重新啟動
啟動線程使用thread.sleep是當(dāng)前線程阻塞一段時間thread.sleep(timeout.infinite)是線程休眠,直到被調(diào)用thread.interrrupt的另一個線程中斷或被thread.abort中止。
一個線程不能對另一個調(diào)用sleep,可以使用thread.suspend來暫停線程,當(dāng)線程對自身調(diào)用thread.suspend將阻塞,直到該線程被另一個線程繼續(xù),當(dāng)一個線程對另一個調(diào)用,該調(diào)用就成為使另一個線程暫停的非阻塞調(diào)用。調(diào)用thread.resume使另一個線程跳出掛起狀態(tài)并使該線程繼續(xù)執(zhí)行,而與調(diào)用thread.suspend的次數(shù)無關(guān)
線程休眠: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使用一個線程等待另一個線程停止
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方法引發(fā)threadabortexception,開始中止此線程的過程,是一個可以由應(yīng)用程序代碼捕獲的特殊異常,resetabort可以取消abort請求,可以組織threadabortexception終止此線程,線程不一定會立即終止,根本不終止。
對尚未啟動的線程調(diào)用abort,則當(dāng)調(diào)用start時該線程將終止。對已經(jīng)掛起的線程調(diào)用abort,則該線程將繼續(xù),然后終止。對阻塞或正在休眠的線程調(diào)用abort,則該線程被中斷,然后終止。
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命令集,模式為開-讀/寫-關(guān) open write/read close
用戶進程進行i/o操作
用戶進程調(diào)用打開命令,獲取文件或設(shè)備的使用權(quán),并返回描述文件或設(shè)備的整數(shù),以描述用戶打開的進程,該進程進行讀寫操作,傳輸數(shù)據(jù),操作完成,進程關(guān)閉,通知os對哪個對象進行了使用。
unix網(wǎng)絡(luò)應(yīng)用編程:bsd的套接字socket,unix的system v 的tli。
套接字編程的基本概念:
網(wǎng)間進程通信:源于單機系統(tǒng),每個進程在自己的地址范圍內(nèi)進行運行,保證互相不干擾且協(xié)調(diào)工作。操作系統(tǒng)為進程之間的通信提供設(shè)施:
unix bsd 管道pipe,命名管道named pipe軟中斷信號signal
unix system v 消息message 共享存儲區(qū) shared memory 信號量semaphore
以上僅限于本機進程之間通信。
端口:網(wǎng)絡(luò)上可以被命名和尋址的通信端口,是操作系統(tǒng)可以分配的一種資源,網(wǎng)絡(luò)通信的最終地址不是主機地址,是可以描述進程的摸中標(biāo)識符。tcp/ip提出協(xié)議端口porotocol port端口,表示通信進程。
進程通過os調(diào)用綁定連接端口,而在傳輸層傳輸給該端口的數(shù)據(jù)傳入進程中處理,同樣在進程的數(shù)據(jù)需要傳給傳輸層也是通過綁定端口實現(xiàn)。進程對端口的操作相當(dāng)于對os中的i/o文件進行操作,每一個端口也對應(yīng)著一個端口號,tcp/ip協(xié)議分為tcp和udp,雖然有相同port number的端口,但是互相也不沖突。 端口號的分配有全局分配,本地分配(動態(tài)分配),當(dāng)進程需要訪問傳輸層,os分配給進程一個端口號。全局分配,就是os固定分配的端口,標(biāo)準(zhǔn)的服務(wù)器都有固定的全局公認(rèn)的端口號提供給服務(wù)。小于256的可以作為保留端口。
地址:網(wǎng)絡(luò)通信中的兩臺機器,可以不再同一個網(wǎng)絡(luò),可能間隔(網(wǎng)關(guān),網(wǎng)橋,路由器等),所以可以分為三層尋址
機器在不同的網(wǎng)絡(luò)則有該網(wǎng)絡(luò)的特定id
同一個網(wǎng)絡(luò)中的機器應(yīng)該有唯一的機器id
一臺機器內(nèi)的進程應(yīng)該有自己的唯一id
通常主機地址=網(wǎng)絡(luò)id+主機id tcp/ip中使用16位端口號來表示進程。
網(wǎng)絡(luò)字節(jié)順序,高價先存,tcp和udp都使用16或32整數(shù)位的高價存儲,在協(xié)議的頭文件中。
半相關(guān):在網(wǎng)絡(luò)中一個進程為協(xié)議+本地地址+端口號=三元組,也叫半相關(guān),表示半部分。
全相關(guān):兩臺機器之間通信需要使用相同協(xié)議
協(xié)議+本地地址+本地端口號+遠(yuǎn)程地址+遠(yuǎn)程端口號 五元組 全相關(guān)。
順序:兩個連續(xù)的報文在網(wǎng)絡(luò)中可能不會通過相同的路徑到達,所以接收的順序會和發(fā)送的順序不一致。順序是接收順序與發(fā)送順序一致。tcp/ip提供該功能。
差錯控制:檢查數(shù)據(jù)差錯:檢查和checksum機制 檢查連接差錯:雙方確認(rèn)應(yīng)答機制。
流控制:雙方傳輸數(shù)據(jù)過程中,保證數(shù)據(jù)傳輸速率的機制,保證數(shù)據(jù)不丟失。
字節(jié)流:把傳輸中的報文當(dāng)作一個字節(jié)序列,不提供任何數(shù)據(jù)邊界。
全雙工/半雙工:兩個方向發(fā)送或一個方向發(fā)送
緩存/帶外數(shù)據(jù):字節(jié)流服務(wù)中,沒有報文邊界,可以同一時刻讀取任意長度的數(shù)據(jù)。為保證傳輸正確或流協(xié)議控制,需要使用緩存,交互型的應(yīng)用程序禁用緩存。
數(shù)據(jù)傳送中,希望不通過常規(guī)傳輸方式傳送給用戶以便及時處理的某一類信息(unix系統(tǒng)的中斷鍵delete,control-c)、終端流控制符control-s、control-q)為帶外數(shù)據(jù)。
客戶/服務(wù)器模式主動請求方式:
1. 打開通信通道,通知本地主機,在某一個公認(rèn)地址上接收客戶請求
2. 等待客戶請求到達端口
3. 接收到重復(fù)服務(wù)請求,處理請求發(fā)送應(yīng)答信號。接收到并發(fā)服務(wù)請求。要激活一個新進程處理客戶請求,unix系統(tǒng)fork、exec,新進程處理客戶請求,不需要對其他請求作出應(yīng)答,服務(wù)完成后,關(guān)閉此進程與客戶的通信鏈路。終止
4. 返回第二步,等待另一個客戶請求。
5. 關(guān)閉服務(wù)端
客戶方:
1. 打開一通信通道,并連接到服務(wù)器所在主機的特定端口。
2. 向服務(wù)器發(fā)送服務(wù)請求報文,等待并接收應(yīng)答;繼續(xù)提出請求…….
3. 請求結(jié)束以后關(guān)閉通信通道并終止。
:
1. 客戶與服務(wù)器進程的作用非對稱,編碼不同
2. 服務(wù)進程先于客戶請求而啟動,系統(tǒng)運行,服務(wù)進程一致存在,直到正常退出或強迫退出
套接字類型:
tcp/ip的socket
sock_stream可靠的面對連接數(shù)據(jù)傳輸,無差錯、無重復(fù)發(fā)送,安照順序發(fā)送接收,內(nèi)設(shè)流量控制,避免數(shù)據(jù)流超限,數(shù)據(jù)為字節(jié)流,無長度限制,ftp流套接字。
sock_dgram 無連接的服務(wù),數(shù)據(jù)包以獨立包的形式發(fā)送,不提供無措保證,數(shù)據(jù)可能丟失重復(fù),發(fā)送接收的順序混亂,網(wǎng)絡(luò)文件系統(tǒng)nfs使用數(shù)據(jù)報式套接字。
sock_ram 接口允許較底層協(xié)議,ip,icmp直接訪問,檢查新的協(xié)議實現(xiàn)或訪問現(xiàn)有服務(wù)中配置的新設(shè)備。
服務(wù)端:
using system.net;
using system.net.sockets;
using system.text;
using system.threading;
thread mythread ;
socket socket;
// 清理所有正在使用的資源。
protected override void dispose( bool disposing )
{
try
{
socket.close();//釋放資源
mythread.abort ( ) ;//中止線程
}
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);
}
//開始監(jiān)聽
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協(xié)議的發(fā)送和接收端
tcp協(xié)議的接收端
using system.net.sockets ; //使用到tcplisten類
using system.threading ; //使用到線程
using system.io ; //使用到streamreader類
int port = 8000; //定義偵聽端口號
private thread ththreadread; //創(chuàng)建線程,用以偵聽端口號,接收信息
private tcplistener tltcplisten; //偵聽端口號
private bool blistener = true; //設(shè)定標(biāo)示位,判斷偵聽狀態(tài)
private networkstream nsstream; //創(chuàng)建接收的基本數(shù)據(jù)流
private streamreader srread;
private system.windows.forms.statusbar statusbar1;
private system.windows.forms.button button1;
private system.windows.forms.listbox listbox1; //從網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流中讀取數(shù)據(jù)
private tcpclient tcclient ;
private void listen ( )
{
try
{
tltcplisten = new tcplistener ( port ) ; //以8000端口號來初始化tcplistener實例
tltcplisten.start ( ) ; //開始監(jiān)聽
statusbar1.text = "正在監(jiān)聽..." ;
tcclient = tltcplisten.accepttcpclient ( ) ; //通過tcp連接請求
nsstream = tcclient.getstream ( ) ; //獲取用以發(fā)送、接收數(shù)據(jù)的網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流
srread=new streamreader(nsstream);//以得到的網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流來初始化streamreader實例
statusbar1.text = "已經(jīng)連接!";
while( blistener ) //循環(huán)偵聽
{
string smessage = srread.readline();//從網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流中讀取一行數(shù)據(jù)
if ( smessage == "stop" ) //判斷是否為斷開tcp連接控制碼
{
tltcplisten.stop(); //關(guān)閉偵聽
nsstream.close(); //釋放資源
srread.close();
statusbar1.text = "連接已經(jīng)關(guān)閉!" ;
ththreadread.abort(); //中止線程
return;
}
string stime = datetime.now.toshorttimestring ( ) ; //獲取接收數(shù)據(jù)時的時間
listbox1.items.add ( stime + " " + smessage ) ;
}
}
catch ( system.security.securityexception )
{
messagebox.show ( "偵聽失敗!" , "錯誤" ) ;
}
}
//開始監(jiān)聽
private void button1_click(object sender, system.eventargs e)
{
ththreadread = new thread ( new threadstart ( listen ) );
ththreadread.start();//啟動線程
button1.enabled=false;
}
// 清理所有正在使用的資源。
protected override void dispose( bool disposing )
{
try
{
tltcplisten.stop(); //關(guān)閉偵聽
nsstream.close();
srread.close();//釋放資源
ththreadread.abort();//中止線程
}
catch{}
if( disposing )
{
if (components != null)
{
components.dispose();
}
}
base.dispose( disposing );
}
tcp協(xié)議的發(fā)送端
using system.net.sockets; //使用到tcplisten類
using system.threading; //使用到線程
using system.io; //使用到streamwriter類
using system.net; //使用ipaddress類、iphostentry類等
private streamwriter swwriter; //用以向網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流傳送數(shù)據(jù)
private networkstream nsstream; //創(chuàng)建發(fā)送數(shù)據(jù)的網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流
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; //通過它實現(xiàn)向遠(yuǎn)程主機提出tcp連接申請
private bool tcpconnect = false; //定義標(biāo)識符,用以表示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地址對應(yīng)主機是否在線
{
messagebox.show ("遠(yuǎn)程主機不在線!" , "錯誤提示!" ) ;
return ;
}
string shostname = iphost.hostname ;
try
{
tcpclient tcpclient = new tcpclient(shostname,8000);//對遠(yuǎn)程主機的8000端口提出tcp連接申請
nsstream = tcpclient.getstream();//通過申請,并獲取傳送數(shù)據(jù)的網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流
swwriter = new streamwriter(nsstream);//使用獲取的網(wǎng)絡(luò)基礎(chǔ)數(shù)據(jù)流來初始化streamwriter實例
button1.enabled = false ;
button2.enabled = true ;
tcpconnect = true ;
statusbar1.text = "已經(jīng)連接!" ;
}
catch
{
messagebox.show ( "無法和遠(yuǎn)程主機8000端口建立連接!" , "錯誤提示!" ) ;
return ;
}
}
//發(fā)送
private void button2_click(object sender, system.eventargs e)
{
if (textbox2.text !="")
{
swwriter.writeline(textbox2.text);//刷新當(dāng)前數(shù)據(jù)流中的數(shù)據(jù)
swwriter.flush();
}
else
{
messagebox.show("發(fā)送信息不能為空!","錯誤提示!");
}
}
// 清理所有正在使用的資源。
protected override void dispose( bool disposing )
{
if ( tcpconnect )
{
swwriter.writeline ( "stop" ) ; //發(fā)送控制碼
swwriter.flush (); //刷新當(dāng)前數(shù)據(jù)流中的數(shù)據(jù)
nsstream.close (); //清除資源
swwriter.close ();
}
if( disposing )
{
if (components != null)
{
components.dispose();
}
}
base.dispose( disposing );
}
異步套接字
beginaccept
public iasyncresult beginaccept{asynccallback callback,object state}
asynccallback異步回調(diào)方法 object state自定義對象, 返回iasyncresult
using system;
namespace mysocket
{
public class stateobject
{
public stateobject(){構(gòu)造函數(shù)邏輯}
}
}à>
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()
{}
}
}
實現(xiàn)主機綁定和端口監(jiān)聽:
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();
}
}
異步回調(diào)方法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(“通話!”+”/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();
}
多線程:
每個窗體自己都在不同的線程上面運行,如果需要在窗體之間交互,需要在線程之間交互
當(dāng)線程sleep,系統(tǒng)就使之退出執(zhí)行隊列,當(dāng)睡眠結(jié)束,系統(tǒng)產(chǎn)生時鐘中斷,使該線程回到執(zhí)行隊列中,回復(fù)線程的執(zhí)行。
如果父線程先于子線程結(jié)束,那么子線程在父線程結(jié)束的時候被迫結(jié)束,thread.join()是父線程等待子線程結(jié)束。abort帶來的是不可回復(fù)的終止線程
起始線程為主線程,前臺線程全部結(jié)束,則主線程可以終止,后臺線程無條件終止。
前臺線程不妨礙程序終止,一旦進程的所有前臺線程終止,則clr調(diào)用任意一個還存活的后臺線程的abort來徹底終止進程。
掛起,睡眠(阻塞,暫停)
thread.suspend不會使線程立即停止執(zhí)行,直到線程到達安全點的時候它才可以將該線程掛起,如果線程尚未運行或這已經(jīng)停止,則不能被掛起,調(diào)用thread.resume使另一個線程跳出掛起狀態(tài),繼續(xù)執(zhí)行。
一個線程不能對另一個線程調(diào)用sleep,但是可以suspend。
lock可以把一段代碼定義為互斥段critical section 互斥段在一個時刻內(nèi)只允許一個線程進入執(zhí)行,其他線程必須等待
多線程公用對象,不應(yīng)該使用lock,monitor提供了線程共享資源的方案,monitor可以鎖定一個對象,線程只有得到鎖才可以對該對象進行操作
一個進程開始至少有一個主線程。系統(tǒng)加載程序時創(chuàng)建主執(zhí)行線程
消息隊列與線程相關(guān)
一開始創(chuàng)建線程就產(chǎn)生消息隊列了,一個線程可以創(chuàng)建多個窗體,而發(fā)給這些窗體的消息都同意發(fā)送到同一個消息隊列中了,消息結(jié)構(gòu)中有msg.hwnd指出該條消息與哪個窗體相關(guān)
dispatchmessage()函數(shù)依照這個保證消息分派處理自動化而且不會出錯。
線程控制方法:
start線程開始運行
sleep 是線程暫停一段指定時間
suspend 線程在到達安全點后暫停
abort 線程到達安全點后停止
resume 重新啟動掛起的線程
join 當(dāng)前線程等待其他線程運行結(jié)束。如果使用超時值,且線程在分配的時間內(nèi)結(jié)束,方法返回true
安全點:代碼中的某些位置,這些位置公共語言運行時可以安全的執(zhí)行自動垃圾回收,即釋放未使用的變量并回收內(nèi)存,調(diào)用線程的abort和suspend方法時,公共語言運行時將分析代碼并確定線程停止運行的適當(dāng)位置。
新聞熱點
疑難解答
圖片精選