每當(dāng)程序建立一個新的套接字連接,也就是說當(dāng)成功調(diào)用accept的時候,將創(chuàng)建一個新的線程來處理服務(wù)器和該客戶端之間的連接,而主程序?qū)⒘⒓捶祷夭⒌却乱粋€連接。
package test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PRintWriter;import java.net.ServerSocket;import java.net.Socket;public class Server { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(8189); int i=5656; while(true){ Socket s = ss.accept(); SocketThread socketThread = new SocketThread(s,++i); new Thread(socketThread).start(); } }}class SocketThread implements Runnable{ private Socket s; private int i; public SocketThread(Socket s,int i) { this.s=s; this.i=i; } public void run(){ try { InputStream is = s.getInputStream(); OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os); BufferedReader bf = new BufferedReader(new InputStreamReader(is)); pw.println("hello,"+i+",enter bye to close"); pw.flush(); boolean flag=true; String input; while((input=bf.readLine())!=null&& flag){ pw.println(i+"==>"+input); if(input.equals("bye")){ flag=false; } pw.flush(); } } catch (IOException e) { e.printStackTrace(); }finally{ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } }}使用上面的服務(wù)器就可以使多個客戶端連接。
window多個cmd中使用telnet 127.0.0.1 8189,就可以創(chuàng)建多個客戶端。
telnet在控制面板中“程序和功能”“打開或關(guān)閉windows功能”里面,要勾選才有用。
下面的程序也行
Socket a = new Socket("127.0.0.1",8189); InputStream is = a.getInputStream(); OutputStream os = a.getOutputStream(); PrintWriter pw = new PrintWriter(os); BufferedReader bf = new BufferedReader(new InputStreamReader(is)); Scanner scanner = new Scanner(System.in); String s; while((s=bf.readLine())!=null){ System.out.println(s); pw.println(scanner.nextLine()); pw.flush(); }多個類一起運(yùn)行也可以看出效果。半關(guān)閉
半關(guān)閉( half-close)提供了這樣一種能力:套接字連接的一端可以終止其輸出,同時仍舊可以接收來自另一端的數(shù)據(jù)。可以通過關(guān)閉一個套接字的輸出流來表示發(fā)送給服務(wù)器的請求數(shù)據(jù)已經(jīng)結(jié)束,但是必須保持輸入流處于打開狀態(tài)。
當(dāng)然,該協(xié)議只適用于一站式( one-shot)的服務(wù),例如HTTP服務(wù),在這種服務(wù)中,客戶端連接服務(wù)器,發(fā)送一個請求,捕獲響應(yīng)信息,然后斷開連接。
void shutdownOutput() 將輸出流設(shè)為“流結(jié)束”。void shutdownInput() 將輸入流設(shè)為“流結(jié)束”。boolean isOutputShutdown() 如果輸出已被關(guān)閉,則返回true。boolean isInputShutdown() 如果輸入已被關(guān)閉,則返回true。其實就是輸入流或者輸出流中一個已經(jīng)用完了,不會用了就把它關(guān)閉了,但是另一個流還有用,不關(guān)閉。可中斷的套接字
當(dāng)連接到一個套接字時,當(dāng)前線程將會被阻塞直到建立連接或產(chǎn)生超時為止。同樣地,當(dāng)通過套接字讀寫數(shù)據(jù)時,當(dāng)前線程也會被阻塞直到操作成功或產(chǎn)生超時為止。
在交互式的應(yīng)用中,也許會考慮為用戶提供一個功能,用以取消那些看似不會成功的連接。但是,當(dāng)線程因套接字長時間無法響應(yīng)而發(fā)生阻塞時,
無法通過調(diào)用interrupt來解除阻塞。
為了中斷套接字操作,可以使用java.nio包提供的一個特性—SocketChannel類。
SocketChannel sc =SocketChannel.open(new InetSocketAddress(hostname, port));通道( channel)并沒有與之相關(guān)聯(lián)的流。實際上,它所擁有的read和write方法都是通過調(diào)用Buffer對象來實現(xiàn)的。 ReadableByteChannel接口和WritableByteChannel接口都聲明了這兩個方法。SocketChannel sc =SocketChannel.open(new InetSocketAddress("127.0.0.1", 8189)); Scanner scanner = new Scanner(sc); InputStream in = Channels.newInputStream(sc); OutputStream put = Channels.newOutputStream(sc);假設(shè)線程正在執(zhí)行打開、讀取或?qū)懭氩僮鳎藭r如果線程發(fā)生中斷,那么這些操作將不會陷入阻塞,而是以拋出異常的方式結(jié)束。InetSocketAddress(String hostname, int port)通過主機(jī)和端口參數(shù)創(chuàng)建一個地址對象,并在創(chuàng)建過程中解析主機(jī)名。如果主機(jī)名不能被解析,那么該地址對象的unresolved屬性將被設(shè)為true。boolean isUnresolved()如果不能解析該地址對象,則返回true。
新聞熱點
疑難解答