基于java TCP網(wǎng)絡(luò)通信的實(shí)例詳解
更新時(shí)間:2013年05月21日 16:37:16 作者:
本篇文章是對(duì)java中TCP網(wǎng)絡(luò)通信的實(shí)例進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
JAVA中設(shè)計(jì)網(wǎng)絡(luò)編程模式的主要有TCP和UDP兩種,TCP是屬于即時(shí)通信,UDP是通過(guò)數(shù)據(jù)包來(lái)進(jìn)行通信,UDP當(dāng)中就會(huì)牽扯到數(shù)據(jù)的解析和傳送。在安全性能方面,TCP要略勝一籌,通信過(guò)程中不容易出現(xiàn)數(shù)據(jù)丟失的現(xiàn)象,有一方中斷,兩方的通信就會(huì)結(jié)束,UDP數(shù)據(jù)包傳送的過(guò)程當(dāng)中,一方中斷,數(shù)據(jù)包有很大的可能丟失,還有可能傳來(lái)的數(shù)據(jù)包的順序是錯(cuò)亂的;在效率方面,UDP要比TCP快的不只是一點(diǎn)點(diǎn)的問(wèn)題,若終端有解析數(shù)據(jù)方法的函數(shù),數(shù)據(jù)包就會(huì)源源不斷的傳送過(guò)來(lái),然后反饋回去。
以上都是我自己的理解,下面是關(guān)于TCP協(xié)議通信的兩個(gè)類(lèi);
Server類(lèi):
package TCP;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class Server {
//服務(wù)器端的輸入流
static BufferedReader br;
//服務(wù)器端的輸出流
static PrintStream ps;
//服務(wù)器相關(guān)的界面組件
static JTextArea text;
JFrame frame;
public Server(){
//服務(wù)器端的界面的實(shí)例化
JFrame frame=new JFrame("服務(wù)器端");
text=new JTextArea();
JScrollPane scroll =new JScrollPane(text);
frame.add(scroll);
frame.setVisible(true);
frame.setSize(300,400);
//這里設(shè)置服務(wù)器端的文本框是不可編輯的
text.setEditable(false);
}
public static void main(String[] args) throws Exception{
new Server(); //生成服務(wù)器界面
//通過(guò)服務(wù)器端構(gòu)造函數(shù) ServerSocket(port) 實(shí)例化一個(gè)服務(wù)器端口
ServerSocket server=new ServerSocket(2000);
text.append("監(jiān)聽(tīng)2000端口"+"\n");
//實(shí)例化一個(gè)接受服務(wù)器數(shù)據(jù)的對(duì)象
Socket client=server.accept();
br =new BufferedReader(new InputStreamReader(client.getInputStream()));
ps =new PrintStream(client.getOutputStream());
String msg;
//如果輸入流不為空,將接受到的信息打印到相應(yīng)的文本框中并反饋回收到的信息
while ((msg =br.readLine())!=null)
{
text.append("服務(wù)器端收到:"+msg+"\n");
ps.println(msg);
if(msg.equals("quit"))
{
text.append("客戶端“2000”已退出!"+"\n");
text.append("服務(wù)器程序?qū)⑼顺觯?);
break;
}
}
ps.close();
br.close();
client.close();
}
}
Client類(lèi):
package TCP;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.net.*;
public class Client implements ActionListener{
//這里有兩個(gè)圖形界面,一個(gè)是連接的frame,另一個(gè)和服務(wù)器通信的界面frame1
private JFrame frame;
private JLabel adress;
private JLabel port;
JTextField adresstext;
JTextField porttext;
JButton connect;
private JFrame frame1;
private JLabel shuru;
private JPanel panel1;
private JPanel panel2;
private JLabel jieshou;
JButton send;
static JTextArea shurukuang;
static TextArea jieshoukuang;
//從服務(wù)端接受的數(shù)據(jù)流
static BufferedReader br1;
//從客戶端輸出的數(shù)據(jù)流
static PrintStream ps;
//從通信界面中的輸入框接受的數(shù)據(jù)流
static BufferedReader br2;
static Socket client;
//將輸入框字符串轉(zhuǎn)換為字符串流所需的字符串的輸入流
static ByteArrayInputStream stringInputStream ;
public Client() {
//連接界面的實(shí)例化
frame=new JFrame();
adress=new JLabel("IP 地址");
port =new JLabel("端口號(hào)");
adresstext=new JTextField("127.0.0.1",10);
porttext=new JTextField("2000",10);
connect=new JButton("連接");
//連接界面的布局
frame.setLayout(new FlowLayout());
frame.add(adress);
frame.add(adresstext);
frame.add(port);
frame.add(porttext);
frame.add(connect);
frame.setVisible(true);
frame.setSize(200,150);
connect.addActionListener(this);
//通信界面的實(shí)例化
frame1=new JFrame();
shuru=new JLabel("請(qǐng)輸入");
shurukuang=new JTextArea("請(qǐng)輸入····",5,40);
panel1=new JPanel();
panel1.add(shuru);
panel1.add(shurukuang);
panel1.setLayout(new FlowLayout());
send=new JButton("發(fā)送");
panel2=new JPanel();
jieshou=new JLabel("已接受");
jieshoukuang=new TextArea(8,60);
jieshoukuang.setEditable(false);
panel2.add(jieshou);
panel2.add(jieshoukuang);
panel2.setLayout(new FlowLayout());
frame1.setLayout(new FlowLayout());
//通信界面都的布局
frame1.add(BorderLayout.NORTH,panel1);
frame1.add(send);
frame1.add(BorderLayout.SOUTH,panel2);
//連接時(shí)通信界面是處于看不到的
frame1.setVisible(false);
frame1.setSize(500,350);
send.addActionListener(this);
}
//兩個(gè)界面當(dāng)中都有相應(yīng)的按鈕時(shí)間,為相應(yīng)的時(shí)間添加動(dòng)作
public void actionPerformed(ActionEvent e) {
if(e.getSource()==connect){
try {
//當(dāng)觸發(fā)連接按鈕時(shí),實(shí)例化一個(gè)客戶端
client=new Socket("127.0.0.1",2000);
//隱藏連接界面,顯示通信界面
frame.setVisible(false);
frame1.setVisible(true);
jieshoukuang.append("已經(jīng)連接上服務(wù)器!"+"\n");
} catch (IOException e1){
System.out.println("鏈接失??!");
e1.printStackTrace();
}
}
//通信界面中的發(fā)送按鈕相應(yīng)的時(shí)間處理
if(e.getSource()==send){
//將輸入框中的字符串轉(zhuǎn)換為字符串流
stringInputStream = new ByteArrayInputStream((shurukuang.getText()).getBytes());
br2 =new BufferedReader(new InputStreamReader(stringInputStream));
String msg;
try{
while((msg=br2.readLine())!=null){
ps.println(msg); //將輸入框中的內(nèi)容發(fā)送給服務(wù)器端
jieshoukuang.append("向服務(wù)器發(fā)送:"+msg+"\n");
jieshoukuang.append("客戶端接受相應(yīng):"+br1.readLine()+"\n");
if(msg.equals("quit"))
{
jieshoukuang.append("客戶端將退出!");
br1.close();
ps.close();
client.close();
frame1.setVisible(false);
break;
}
}
}catch(IOException e2){
System.out.println("讀輸入框數(shù)據(jù)出錯(cuò)!");
}
shurukuang.setText("");
}
}
public static void main(String[] args) throws IOException{
new Client(); //實(shí)例化連接界面
client=new Socket("127.0.0.1",2000);
//從服務(wù)端接受的數(shù)據(jù)
br1=new BufferedReader(new InputStreamReader(client.getInputStream()));
//從客戶端輸出的數(shù)據(jù)
ps =new PrintStream(client.getOutputStream());
}
}
寫(xiě)完這兩個(gè)類(lèi)以后還是有幾個(gè)問(wèn)題:
1)main 函數(shù)為什么非要用 static 來(lái)修飾?
2)緩沖對(duì)象 BufferedReader 為什么不能直接用于判斷,非要將讀到的數(shù)據(jù)賦值給字符串來(lái)進(jìn)行操作?
3)在連接界面當(dāng)中的 Connect 按鈕事件 當(dāng)中我有實(shí)例化一個(gè) 客戶端的對(duì)象,但是我注釋掉主函數(shù)當(dāng)中 client=new Socket("127.0.0.1",2000); 的這一句的時(shí)候,就會(huì)發(fā)現(xiàn)拋出 NULLPOINTEXCEPTION 異常,我很不理解?
希望有看到這文章的大牛們能不吝賜教,我也正在不停的翻著《Think in java》希望在某個(gè)不起眼的角落里面發(fā)現(xiàn)我的答案。
以上都是我自己的理解,下面是關(guān)于TCP協(xié)議通信的兩個(gè)類(lèi);
Server類(lèi):
復(fù)制代碼 代碼如下:
package TCP;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class Server {
//服務(wù)器端的輸入流
static BufferedReader br;
//服務(wù)器端的輸出流
static PrintStream ps;
//服務(wù)器相關(guān)的界面組件
static JTextArea text;
JFrame frame;
public Server(){
//服務(wù)器端的界面的實(shí)例化
JFrame frame=new JFrame("服務(wù)器端");
text=new JTextArea();
JScrollPane scroll =new JScrollPane(text);
frame.add(scroll);
frame.setVisible(true);
frame.setSize(300,400);
//這里設(shè)置服務(wù)器端的文本框是不可編輯的
text.setEditable(false);
}
public static void main(String[] args) throws Exception{
new Server(); //生成服務(wù)器界面
//通過(guò)服務(wù)器端構(gòu)造函數(shù) ServerSocket(port) 實(shí)例化一個(gè)服務(wù)器端口
ServerSocket server=new ServerSocket(2000);
text.append("監(jiān)聽(tīng)2000端口"+"\n");
//實(shí)例化一個(gè)接受服務(wù)器數(shù)據(jù)的對(duì)象
Socket client=server.accept();
br =new BufferedReader(new InputStreamReader(client.getInputStream()));
ps =new PrintStream(client.getOutputStream());
String msg;
//如果輸入流不為空,將接受到的信息打印到相應(yīng)的文本框中并反饋回收到的信息
while ((msg =br.readLine())!=null)
{
text.append("服務(wù)器端收到:"+msg+"\n");
ps.println(msg);
if(msg.equals("quit"))
{
text.append("客戶端“2000”已退出!"+"\n");
text.append("服務(wù)器程序?qū)⑼顺觯?);
break;
}
}
ps.close();
br.close();
client.close();
}
}
Client類(lèi):
復(fù)制代碼 代碼如下:
package TCP;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.net.*;
public class Client implements ActionListener{
//這里有兩個(gè)圖形界面,一個(gè)是連接的frame,另一個(gè)和服務(wù)器通信的界面frame1
private JFrame frame;
private JLabel adress;
private JLabel port;
JTextField adresstext;
JTextField porttext;
JButton connect;
private JFrame frame1;
private JLabel shuru;
private JPanel panel1;
private JPanel panel2;
private JLabel jieshou;
JButton send;
static JTextArea shurukuang;
static TextArea jieshoukuang;
//從服務(wù)端接受的數(shù)據(jù)流
static BufferedReader br1;
//從客戶端輸出的數(shù)據(jù)流
static PrintStream ps;
//從通信界面中的輸入框接受的數(shù)據(jù)流
static BufferedReader br2;
static Socket client;
//將輸入框字符串轉(zhuǎn)換為字符串流所需的字符串的輸入流
static ByteArrayInputStream stringInputStream ;
public Client() {
//連接界面的實(shí)例化
frame=new JFrame();
adress=new JLabel("IP 地址");
port =new JLabel("端口號(hào)");
adresstext=new JTextField("127.0.0.1",10);
porttext=new JTextField("2000",10);
connect=new JButton("連接");
//連接界面的布局
frame.setLayout(new FlowLayout());
frame.add(adress);
frame.add(adresstext);
frame.add(port);
frame.add(porttext);
frame.add(connect);
frame.setVisible(true);
frame.setSize(200,150);
connect.addActionListener(this);
//通信界面的實(shí)例化
frame1=new JFrame();
shuru=new JLabel("請(qǐng)輸入");
shurukuang=new JTextArea("請(qǐng)輸入····",5,40);
panel1=new JPanel();
panel1.add(shuru);
panel1.add(shurukuang);
panel1.setLayout(new FlowLayout());
send=new JButton("發(fā)送");
panel2=new JPanel();
jieshou=new JLabel("已接受");
jieshoukuang=new TextArea(8,60);
jieshoukuang.setEditable(false);
panel2.add(jieshou);
panel2.add(jieshoukuang);
panel2.setLayout(new FlowLayout());
frame1.setLayout(new FlowLayout());
//通信界面都的布局
frame1.add(BorderLayout.NORTH,panel1);
frame1.add(send);
frame1.add(BorderLayout.SOUTH,panel2);
//連接時(shí)通信界面是處于看不到的
frame1.setVisible(false);
frame1.setSize(500,350);
send.addActionListener(this);
}
//兩個(gè)界面當(dāng)中都有相應(yīng)的按鈕時(shí)間,為相應(yīng)的時(shí)間添加動(dòng)作
public void actionPerformed(ActionEvent e) {
if(e.getSource()==connect){
try {
//當(dāng)觸發(fā)連接按鈕時(shí),實(shí)例化一個(gè)客戶端
client=new Socket("127.0.0.1",2000);
//隱藏連接界面,顯示通信界面
frame.setVisible(false);
frame1.setVisible(true);
jieshoukuang.append("已經(jīng)連接上服務(wù)器!"+"\n");
} catch (IOException e1){
System.out.println("鏈接失??!");
e1.printStackTrace();
}
}
//通信界面中的發(fā)送按鈕相應(yīng)的時(shí)間處理
if(e.getSource()==send){
//將輸入框中的字符串轉(zhuǎn)換為字符串流
stringInputStream = new ByteArrayInputStream((shurukuang.getText()).getBytes());
br2 =new BufferedReader(new InputStreamReader(stringInputStream));
String msg;
try{
while((msg=br2.readLine())!=null){
ps.println(msg); //將輸入框中的內(nèi)容發(fā)送給服務(wù)器端
jieshoukuang.append("向服務(wù)器發(fā)送:"+msg+"\n");
jieshoukuang.append("客戶端接受相應(yīng):"+br1.readLine()+"\n");
if(msg.equals("quit"))
{
jieshoukuang.append("客戶端將退出!");
br1.close();
ps.close();
client.close();
frame1.setVisible(false);
break;
}
}
}catch(IOException e2){
System.out.println("讀輸入框數(shù)據(jù)出錯(cuò)!");
}
shurukuang.setText("");
}
}
public static void main(String[] args) throws IOException{
new Client(); //實(shí)例化連接界面
client=new Socket("127.0.0.1",2000);
//從服務(wù)端接受的數(shù)據(jù)
br1=new BufferedReader(new InputStreamReader(client.getInputStream()));
//從客戶端輸出的數(shù)據(jù)
ps =new PrintStream(client.getOutputStream());
}
}
寫(xiě)完這兩個(gè)類(lèi)以后還是有幾個(gè)問(wèn)題:
1)main 函數(shù)為什么非要用 static 來(lái)修飾?
2)緩沖對(duì)象 BufferedReader 為什么不能直接用于判斷,非要將讀到的數(shù)據(jù)賦值給字符串來(lái)進(jìn)行操作?
3)在連接界面當(dāng)中的 Connect 按鈕事件 當(dāng)中我有實(shí)例化一個(gè) 客戶端的對(duì)象,但是我注釋掉主函數(shù)當(dāng)中 client=new Socket("127.0.0.1",2000); 的這一句的時(shí)候,就會(huì)發(fā)現(xiàn)拋出 NULLPOINTEXCEPTION 異常,我很不理解?
希望有看到這文章的大牛們能不吝賜教,我也正在不停的翻著《Think in java》希望在某個(gè)不起眼的角落里面發(fā)現(xiàn)我的答案。
相關(guān)文章
net.sf.json.JSONObject 為null 的判斷方法
下面小編就為大家?guī)?lái)一篇net.sf.json.JSONObject 為null 的判斷方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02SpringBoot與spring security的結(jié)合的示例
這篇文章主要介紹了SpringBoot與spring security的結(jié)合的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03SpringBoot?調(diào)用外部接口的三種實(shí)現(xiàn)方法
Spring Boot調(diào)用外部接口的方式有多種,常見(jiàn)的有以下三種方式:RestTemplate、Feign 和 WebClient,本文就詳細(xì)介紹一下,感興趣的可以了解一下2023-08-08spring boot+ redis 接口訪問(wèn)頻率限制的實(shí)現(xiàn)
這篇文章主要介紹了spring boot+ redis 接口訪問(wèn)頻率限制的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01一篇文章帶你了解SpringMVC數(shù)據(jù)綁定
這篇文章主要給大家介紹了關(guān)于如何通過(guò)一篇文章弄懂Spring MVC的參數(shù)綁定,文中通過(guò)示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08JDK動(dòng)態(tài)代理提高代碼可維護(hù)性和復(fù)用性利器
這篇文章主要為大家介紹了JDK動(dòng)態(tài)代理提高代碼可維護(hù)性和復(fù)用性利器,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10