1. 程式人生 > 實用技巧 >用JAVA實現兩個程序間的網路通訊

用JAVA實現兩個程序間的網路通訊

實現是基於UDP協議的的,兩個程序(兩個java程式)互相傳送,並接受各自發送的資料的功能。
兩個包模擬通訊的兩個程序(人),由於是映象程式碼,只貼出一個包中的程式碼,通訊另一方只要做傳送埠、ip的修改即可;
程式碼頂層設計如下:

package net.oneperson;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.UnknownHostException;

/*1. 實現基於UDP協議的的,兩個程序(兩個java程式)互相傳送,並接受各自發送的資料的功能。
        (可以參考課堂上edition3非多執行緒版本或edition4多執行緒版本實現,都可以哈)
    
*/ public class Oneperson { //主類應該包含主要配置資訊,啟動首發執行緒; public static boolean isSenderoff = false; public static Object lockClose = new Object();//用來控制訪問共享變數isSenderoff的鎖 public static void main(String args[]) throws SocketException, UnknownHostException { DatagramSocket datagramSocket
= new DatagramSocket(10086);//定義本人收發埠 ReceiverTask receiverTask = new ReceiverTask(datagramSocket); Thread myReceive = new Thread(receiverTask); myReceive.start(); String targetIp="127.0.0.1";//對方的Ip,發給本機就是本地ip int targetPort = 8888;//對方的埠 SenderTask senderTask = new
SenderTask(datagramSocket,targetIp,targetPort); Thread mySend= new Thread(senderTask); mySend.start(); } }
package net.oneperson;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ReceiverTask implements Runnable {
    private DatagramSocket datagramSocket;

    public ReceiverTask(DatagramSocket datagramSocket) {
        this.datagramSocket = datagramSocket;
    }


    @Override
    public void run() {
        //準備接收資料的package
        byte[] buf = new byte[1024];
        int off = 0;
        DatagramPacket datagramPacket = new DatagramPacket(buf, off, buf.length - off);
        boolean isFinish = false;

        //用包裝包的接收函式一直接收資料
        try {
            while (true) {
                isFinish = receiveData(datagramSocket, datagramPacket);
                if (isFinish) break;//收到再見之前,一直收;收到再見,不再接收,轉到finally判斷是否可以關閉socket

            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            while (true) {//只要傳送方還沒說要結束,執行緒一直在這裡空轉,等待
                synchronized (Oneperson.lockClose) {
                    if (Oneperson.isSenderoff) {
                        // datagramSocket.close();//這麼寫也是可以的
                        break;
                    }
                    try {
                        Oneperson.lockClose.wait(100);//可以在任何物件上呼叫wait,阻塞的是執行該物件的執行緒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }


            }

            //可以關閉了
            datagramSocket.close();
        }
    }

    /*函式:用於接收資料,並在函式將其內容顯示,並判斷是否收到886,是的話返回true*/
    private boolean receiveData(DatagramSocket datagramSocket, DatagramPacket receivePacket) throws IOException {

        datagramSocket.receive(receivePacket);//接收資料包

        byte[] buf = receivePacket.getData();//從資料包獲得位元組資料
        int off = receivePacket.getOffset();//獲得實際收到位元組資料的起始位置
        int length = receivePacket.getLength();//本次實際收到資料的長度;
        //解析接收到的位元組資料,並將其轉化為字串
        String s = new String(buf, off, length);
        System.out.println(receivePacket.getAddress() + ":" + receivePacket.getPort() + " ," + s);
        if ("886".equals(s)) {
            return true;
        }
        return false;
    }

}
package net.oneperson;

import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class SenderTask implements Runnable{
    private DatagramSocket socket;
    private static InetAddress targetIp; //要傳送的IP地址
    private static int targetPort;//要傳送的埠



    //構造方法引數:一個socket,targetID,targetPoet 介面,目標ID,目標埠
    public SenderTask(DatagramSocket socket, String targetIp,int targrtPort) throws UnknownHostException {
        this.targetIp=InetAddress.getByName(targetIp);
        this.targetPort=targrtPort;
        this.socket = socket;
    }
    @Override//執行方法
    public void run() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//因為是健康輸入,用System.in;如果是檔案,需要一個File路徑或目錄
        String dataSend;
        while(true){
            try {
                //傳送有輸入來,就一直髮送
                if (((dataSend =br.readLine())==null)) break;
                sendDate(dataSend,socket);
                if(dataSend.equals("886")){
                    //每次都檢查自己是不是傳送了886,是的話將標記位標記
                    synchronized (Oneperson.lockClose){
                        Oneperson.isSenderoff = true;
                    }
                    break;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    //SendDate,Q1-為什麼要定義成static
    //這個方法是在哪裡被使用?run中
    //它要接收引數,傳送的資訊資料,傳送的介面
    private static void sendDate(String data,DatagramSocket datagramSocket) throws IOException {
        byte [] dataBytes = data.getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(dataBytes,0,dataBytes.length,targetIp,targetPort);
        datagramSocket.send(datagramPacket);//send()方法
    }
}

執行結果展示: