日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java多线程与网络编程综合使用

發(fā)布時(shí)間:2024/1/17 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java多线程与网络编程综合使用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

處理多線程與網(wǎng)絡(luò)編程最為經(jīng)典的例子莫過于聊天室,那我就聊天室案例作為一個(gè)回顧。
首先,我們來看以下代碼:

package MultiTCP;import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 必須先啟動(dòng)再連接 * 1、創(chuàng)建服務(wù)器 指定端口 ServerSocket(int port) * 2、接收客戶端的連接 阻塞式 * 3、發(fā)送數(shù)據(jù)+接收數(shù)據(jù) * * 接收多個(gè)客戶端 */ @SuppressWarnings("all") public class MultiServer { public static void main(String[] args) throws IOException { //1、創(chuàng)建服務(wù)器 指定端口 ServerSocket server = new ServerSocket(8888); while(true)//死循環(huán) 一個(gè)accept 一個(gè)客戶端 { //2、接收客戶端的連接 Socket socket = server.accept(); System.out.println("一個(gè)客戶端建立連接"); //2、發(fā)送數(shù)據(jù) String msg = "歡迎使用"; //3、輸出流 /*BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())); bw.write(msg); bw.newLine();//一定要加行結(jié)束符,不然讀不到數(shù)據(jù) bw.flush();*/ DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); dos.writeUTF(msg); dos.flush(); } } }

?

package MultiTCP;import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; /** * 1、創(chuàng)建客戶端 必須指定服務(wù)器+端口 此時(shí)就在連接 * Socket(String host,int port) * 2、接收數(shù)據(jù)+發(fā)送數(shù)據(jù) */ @SuppressWarnings("all") public class Client { public static void main(String[] args) throws UnknownHostException, IOException { //1、創(chuàng)建客戶端 必須指定服務(wù)器+端口 此時(shí)就在連接 Socket client = new Socket("localhost",8888); //2、接收數(shù)據(jù) /*BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())); String echo = br.readLine();//阻塞式方法 System.out.println(echo);*/ DataInputStream dis = new DataInputStream(client.getInputStream()); String echo = dis.readUTF(); System.out.println(echo); } }

?

以上代碼存在的問題
服務(wù)器為一個(gè)客戶端發(fā)送數(shù)據(jù)完畢才能連接下一個(gè)客戶端。
因此,為了解決上述的問題,我們需要為服務(wù)器端創(chuàng)建多線程操作。

首先我們需要為聊天室添加發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。

package CSNet;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 創(chuàng)建服務(wù)器 */ @SuppressWarnings("all") public class Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(9999); Socket client = server.accept(); //寫出數(shù)據(jù) //輸入流 DataInputStream dis = new DataInputStream(client.getInputStream()); String msg = dis.readUTF(); System.out.println("服務(wù)器收到"+msg); //輸出流 DataOutputStream dos = new DataOutputStream(client.getOutputStream()); dos.writeUTF("服務(wù)器發(fā)送給客戶端"+msg); dos.flush(); } }

?

package CSNet;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; /** * 創(chuàng)建客戶端:發(fā)送數(shù)據(jù)+接收數(shù)據(jù) * 寫出數(shù)據(jù):輸出流 * 讀取數(shù)據(jù):輸入流 * 輸入流與輸出流在同一個(gè)線程內(nèi),因此我們應(yīng)該讓 輸入流與輸出流彼此獨(dú)立 */ @SuppressWarnings("all") public class Client { public static void main(String[] args) throws UnknownHostException, IOException { Socket client = new Socket("localhost",9999); //控制臺(tái)的輸入流 BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); DataOutputStream dos = new DataOutputStream(client.getOutputStream()); DataInputStream dis = new DataInputStream(client.getInputStream()); while(true) { String info = console.readLine(); //輸出流 dos.writeUTF(info); dos.flush(); //輸入流 String msg = dis.readUTF(); System.out.println(msg); } } }

?

以上的代碼存在輸入流與輸出流在同一個(gè)線程內(nèi)問題,因此我們應(yīng)該讓輸入流與輸出流彼此獨(dú)立。


接下來我們是需要實(shí)現(xiàn)多線程,讓輸入流與輸出流分離。對(duì)客戶端實(shí)現(xiàn)多線程。

客戶端發(fā)送數(shù)據(jù)

package ThreadNet;import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 發(fā)送數(shù)據(jù)線程:用于發(fā)送數(shù)據(jù) */ public class Send implements Runnable{ //控制臺(tái)的輸入流 private BufferedReader console; //管道的數(shù)據(jù)輸出流 private DataOutputStream dos; //控制線程標(biāo)識(shí) private boolean isRunning = true; //初始化 public Send() { console = new BufferedReader(new InputStreamReader(System.in)); } public Send(Socket client) { this(); try { dos = new DataOutputStream(client.getOutputStream()); } catch (IOException e) { } } //1、從控制臺(tái)接收數(shù)據(jù) private String getMsgFromConsole() { try { return console.readLine(); } catch (IOException e) { } return ""; } /** * 1、從控制臺(tái)接收數(shù)據(jù) * 2、發(fā)送數(shù)據(jù) */ public void send() { String msg = getMsgFromConsole(); try { if(null!=msg&& !msg.equals("")) { dos.writeUTF(msg); dos.flush();//強(qiáng)制刷新 } } catch (IOException e) { isRunning = false;//發(fā)送失敗,提示關(guān)閉線程 CloseUtil.closeAll(dos,console);//如果不能發(fā)送成功,直接關(guān)閉流。 } } @Override public void run() { //線程體 while(isRunning) { send(); } } }

?

客戶端接收數(shù)據(jù)

package ThreadNet;import java.io.DataInputStream; import java.io.IOException; import java.net.Socket;/** * 接收線程:用于接收數(shù)據(jù) */ public class Receive implements Runnable{ //管道的數(shù)據(jù)輸入流 private DataInputStream dis ; //線程標(biāo)識(shí) private boolean isRunning = true; public Receive() { } public Receive(Socket client) { try { dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); } } //接收數(shù)據(jù)的方法 public String receive() { String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); } return msg; } @Override public void run() { //線程體 while(isRunning){ System.out.println(receive()); } } }

?

客戶端

package ThreadNet;import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException;/** * 創(chuàng)建客戶端:發(fā)送數(shù)據(jù)+接收數(shù)據(jù) * 寫出數(shù)據(jù):輸出流 * 讀取數(shù)據(jù):輸入流 * 輸入流與輸出流在同一個(gè)線程內(nèi) 應(yīng)該獨(dú)立出來 */ public class Client { public static void main(String[] args) throws UnknownHostException, IOException { Socket client = new Socket("localhost",9999); new Thread(new Send(client)).start();//一條路徑 new Thread(new Receive(client)).start();//一條路徑 } }

?

服務(wù)器

package ThreadNet;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 創(chuàng)建服務(wù)器 */ public class Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(9999); while(true){ Socket client = server.accept(); //寫出數(shù)據(jù) //輸入流 DataInputStream dis = new DataInputStream(client.getInputStream()); //輸出流 DataOutputStream dos = new DataOutputStream(client.getOutputStream()); while(true) { String msg = dis.readUTF(); //System.out.println(msg); dos.writeUTF("服務(wù)器收到數(shù)據(jù)并返回"+msg); dos.flush(); } } } }

?

關(guān)閉流

package ThreadNet;import java.io.Closeable; import java.io.IOException;/*** 關(guān)閉流的方法*/ public class CloseUtil { public static void closeAll(Closeable ... io) { for(Closeable temp:io) { if(null==temp) { try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

這個(gè)方仍然存在問題,服務(wù)器端只能夠一個(gè)一個(gè)的接收,必須要等到上一條執(zhí)行完,才能進(jìn)入下一條,存在所謂的先后順序,并不具備多線程的功能。因此我們也需要對(duì)服務(wù)器進(jìn)行多線程。


服務(wù)器

package MultiServer;import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; /** * 創(chuàng)建服務(wù)器 */ public class Server { private List<MyChannel> all = new ArrayList<>(); public static void main(String[] args) throws IOException { new Server().start(); } public void start() throws IOException { ServerSocket server = new ServerSocket(9999); while(true) { Socket client = server.accept(); MyChannel channel = new MyChannel(client); all.add(channel);//統(tǒng)一管理 new Thread(channel).start();//一條道路 } } /** * 內(nèi)部類 * 一個(gè)客戶端 一條道路 * 1、輸入流 * 2、輸出流 * 3、接收數(shù)據(jù) * 4、發(fā)送數(shù)據(jù) * @author Administrator * */ class MyChannel implements Runnable { private DataInputStream dis; private DataOutputStream dos; private boolean isRunning = true; private String name; public MyChannel() { } //初始化 public MyChannel(Socket client) { try { dis = new DataInputStream(client.getInputStream()); dos = new DataOutputStream(client.getOutputStream()); this.name = dis.readUTF(); //System.out.println(this.name); this.send("歡迎進(jìn)入聊天室"); sendOthers(this.name+"進(jìn)入了聊天室",true); } catch (IOException e) { CloseUtil.closeAll(dos,dis); isRunning = false; } } //接收數(shù)據(jù) private String receive() { String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { CloseUtil.closeAll(dis); isRunning = false; all.remove(this);//移除自身 } return msg; } //發(fā)送數(shù)據(jù) private void send(String msg) { if(null==msg||msg.equals("")) { return; } try { dos.writeUTF(msg); dos.flush(); } catch (IOException e) { CloseUtil.closeAll(dos); isRunning = false; all.remove(this);//移除自身 } } //發(fā)送給其他客戶端 private void sendOthers(String msg,boolean sys) { //是否為私聊 約定 if(msg.startsWith("@")&& msg.indexOf(":")>-1) { //獲取name String name = msg.substring(1,msg.indexOf(":")); String contant = msg.substring(msg.indexOf(":")+1); for(MyChannel other:all) { if(other.name.equals(name)) { other.send(this.name+"對(duì)你悄悄的說:"+contant); } } } else { for(MyChannel other:all) { if(other ==this) { continue; } if(sys==true)//系統(tǒng)信息 { other.send("系統(tǒng)信息:"+msg); } else { //發(fā)送其它客戶端 other.send(this.name+"對(duì)所有人說"+msg); } } } /* //遍歷容器 for(MyChannel others:all) { if(others == this) { continue; } //發(fā)送給其他客戶端 others.send(msg); }*/ } @Override public void run() { while(isRunning) { sendOthers(receive(),false); } } } }

發(fā)送信息(供客服端使用)

package MultiServer;import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 發(fā)送數(shù)據(jù)線程:用于發(fā)送數(shù)據(jù) */ public class Send implements Runnable{ //控制臺(tái)輸入流 private BufferedReader console; //管道輸出流 private DataOutputStream dos; //控制線程標(biāo)識(shí) private boolean isRunning = true; //名稱 private String name; //初始化 public Send() { console = new BufferedReader(new InputStreamReader(System.in)); } public Send(Socket client,String name) { this(); try { dos = new DataOutputStream(client.getOutputStream()); this.name = name; send(this.name); } catch (IOException e) { //e.printStackTrace(); } } //1、從控制臺(tái)接收數(shù)據(jù) private String getMsgFromConsole() { try { return console.readLine(); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 1、從控制臺(tái)接收數(shù)據(jù) * 2、發(fā)送數(shù)據(jù) */ public void send(String msg) { try { if(null!=msg&& !msg.equals("")) { dos.writeUTF(msg); dos.flush();//強(qiáng)制刷新 } } catch (IOException e) { //e.printStackTrace(); isRunning = false; CloseUtil.closeAll(dos,console); } } @Override public void run() { while(isRunning) { send( getMsgFromConsole()); } } }

接收信息(供客服端使用)

package MultiServer;import java.io.DataInputStream; import java.io.IOException; import java.net.Socket;/** * 接收線程:用于接收數(shù)據(jù) */ public class Receive implements Runnable{ //管道的數(shù)據(jù)輸入流 private DataInputStream dis ; //線程標(biāo)識(shí) private boolean isRunning = true; public Receive() { } public Receive(Socket client) { try { dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); } } //接收數(shù)據(jù)的方法 public String receive() { String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); } return msg; } @Override public void run() { //線程體 while(isRunning){ System.out.println(receive()); } } }

客戶端

package MultiServer;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 創(chuàng)建客戶端:發(fā)送數(shù)據(jù)+接收數(shù)據(jù) * 寫出數(shù)據(jù):輸出流 * 讀取數(shù)據(jù):輸入流 * 輸入流與輸出流在同一個(gè)線程內(nèi) 應(yīng)該獨(dú)立出來 * 加入名稱 */ public class Client { public static void main(String[] args) throws IOException { System.out.println("請(qǐng)輸入用戶名:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String name = br.readLine(); if(name.equals("")) { return; } Socket client = new Socket("localhost",9999); new Thread(new Send(client,name)).start();//一條路徑 new Thread(new Receive(client)).start();//一條路徑 } }

關(guān)閉流

package MultiServer;import java.io.Closeable; import java.io.IOException;/*** 關(guān)閉流的方法*/ public class CloseUtil { public static void closeAll(Closeable ... io) { for(Closeable temp:io) { if(null==temp) { try { temp.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

運(yùn)行結(jié)果:
Client1

Client2

轉(zhuǎn)載于:https://www.cnblogs.com/lengzhijun/p/4580271.html

總結(jié)

以上是生活随笔為你收集整理的Java多线程与网络编程综合使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。