Java基礎 網絡編程 Socket UDP TCP URL

網絡編程

  • 網絡模型
    • OSI參考模型
    • TCP/IP參考模型
  • 網絡通訊要素
    • IP地址
    • 端口號
    • 傳輸協議

網絡通訊要素

  • 網絡中設備的標識
    • 不易記憶,可用主機名
    • 本地迴環地址: 127.0.0.1 主機名: localhost
  • 端口號
    • 用於標識進程的邏輯地址,不同進程的標識
    • 有效端口:0~65535,其中0~1024系統使用或保留端口
  • 傳輸協議
    • 通訊的規則
    • 常見協議:TCP,UDP

TCP和UDP

  • UDP
    • 將數據及源和目的封裝成數據包中,不需要建立連接
    • 每個數據報的大小限制在64K內
    • 因無連接,是不可靠協議
    • 不需要建立連接,速度快
  • TCP
    • 建立連接,形成傳輸數據的通道
    • 在連接中進行大數據量傳輸
    • 通過三次握手完成連接,是可靠協議
    • 必須建立連接,效率會稍低

Socket

  • Socket就是爲網絡服務提供的一種機制
  • 通信的兩端都有Socket
  • 網絡通信其實就是Socket間的通信
  • 數據在兩個Socket間通過IO傳輸

UDP 發送接收

UDP發送端

import java.net.*;
class UdpDemo
{
    public static void main(String[] args) throws Exception
    {
        String data="hello";
        //確定數據,並封裝成數據包
        byte[] b=data.getBytes();
        InetAddress ia=InetAddress.getByName("192.168.0.104");
        //1.創建UDP服務,通過DatagramSocket對象
        DatagramSocket ds=new DatagramSocket();
        //封裝成數據包
        DatagramPacket dp=new DatagramPacket(b,b.length,ia,10000);
        //通過socket服務,將已有的數據包發送出去通過send方法
        ds.send(dp);
        //關閉資源
        ds.close();
    }
}

UDP接收端

import java.net.*;
class UdpReceive
{
    public static void main(String[] args) throws Exception
    {
        byte[] b=new byte[1024];
        DatagramSocket ds=new DatagramSocket(10000);
        DatagramPacket dp=new DatagramPacket(b,1024);
        ds.receive(dp);
        System.out.println(dp.getAddress().getHostAddress());
        System.out.println(dp.getPort());
        System.out.println(new String(dp.getData(),0,dp.getLength()));
        ds.close();
    }
}

重複接收,通過鍵盤輸入發送數據

發送端

import java.net.*;
import java.io.*;
class UdpSender
{
    public static void main(String[] args) throws Exception
    {
        String data="";
        //確定數據,並封裝成數據包
        InetAddress ia=InetAddress.getByName("192.168.0.104");
        //1.創建UDP服務,通過DatagramSocket對象
        DatagramSocket ds=new DatagramSocket();
        //通過socket服務,將已有的數據包發送出去通過send方法
        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
        while(true)
        {
            data=bufr.readLine()
            //封裝成數據包
            byte[] buf=data.getBytes();
            DatagramPacket dp=new DatagramPacket(buf,buf.length,ia,10000);
            ds.send(dp);
            if(data.equals("bye"))
                break;
        }
        //關閉資源
        ds.close();
    }
}

接收端

import java.net.*;
class UdpReceive
{
    public static void main(String[] args) throws Exception
    {
        byte[] buf=new byte[1024];
        String senderAddress="";
        String data="";
        int senderPort=0;
        int dataLength=0;
        DatagramSocket ds=new DatagramSocket(10000);
        DatagramPacket dp=new DatagramPacket(buf,1024);
        while(true)
        {
            ds.receive(dp);
            senderAddress=dp.getAddress().getHostAddress();
            senderPort=dp.getPort();
            dataLength=dp.getLength();
            data=new String(dp.getData(),0,dataLength);

            System.out.println(senderAddress+":"+senderPort+" "+data);
            if(data.equals("bye"))
                break;

        }
        ds.close();
    }
}

UDP 實現聊天

  • 創建一個客戶端,一個服務端
  • 分別綁定到10000和20000端口
  • 創建兩個線程
  • 1個接收線程
    • 通過提供的Socket和綁定的端口監聽消息,並顯示
  • 1個發送線程
    • 通過提供的Socket和綁定的端口發送消息到包 DatagramPacket 指定的地址和端口

UDP聊天程序1

import java.net.*;
import java.io.*;
//接受消息線程
class RecRun implements Runnable
{
    DatagramSocket ds;

    String data;

    RecRun(DatagramSocket ds)
    {
        this.ds=ds;

    }
    public void run()
    {
        while(true)
        {
            try
            {

                byte[] bufr=new byte[1024];
                DatagramPacket dp=new DatagramPacket(bufr,bufr.length);
                ds.receive(dp);

                data=new String(dp.getData(),0,dp.getLength());
                System.out.println("");

                System.out.println(dp.getAddress().getHostAddress()+":"+dp.getPort()+" 說:");
                System.out.println(data);

                System.out.println("");
                if(data.equals("bye"))
                {
                    System.out.println("對方結束了通話,回車退出.");
                    break;
                }
            }
            catch(Exception e)
            {
                //e.printStackTrace();
                break;
            }
        }
        ds.close();
    }
}
//發送消息線程
class SendRun implements Runnable
{
    DatagramSocket ds;
    DatagramPacket dp;
    String line;
    SendRun(DatagramSocket ds,DatagramPacket dp)
    {
        this.ds=ds;
        this.dp=dp;
    }
    public void run()
    {
        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
        while(true)
        {

            try
            {
                System.out.println("請輸入:");
                line=bufr.readLine();

                dp.setData(line.getBytes());
                ds.send(dp);
            }
            catch(Exception e)
            {

                break;
            }
            if(line.equals("bye"))
                break;
        }
        ds.close();
    }
}
class ChatServer
{
    public static void main(String[] args) throws Exception
    {
        //創建發送目的包
        int port=20000;
        byte[] buf=new byte[1024];
        InetAddress ia=InetAddress.getByName("192.168.0.104");
        DatagramPacket dp=new DatagramPacket(buf,buf.length,ia,port);

        //創建套接字,綁定本地端口號
        DatagramSocket ds=new DatagramSocket(10000);

        //接收包


        //創建接收消息線程,根據綁定的端口號進行監聽
        Thread recThread=new Thread(new RecRun(ds));
        //創建發送消息線程,通過綁定的端口進行發送,發送到DatagramPacket 中 InetAddress 的IP地址和port端口號提供的接收地址.
        Thread sendThread=new Thread(new SendRun(ds,dp));

        recThread.start();
        sendThread.start();
    }
}

UDP聊天程序2

import java.net.*;
import java.io.*;

class ChatClient
{
    public static void main(String[] args) throws Exception
    {

        byte[] bufs=new byte[1024];
        //發送到的端口
        int port=10000;
        //發送到的地址
        InetAddress ia=InetAddress.getByName("192.168.0.104");
        //套接字
        DatagramSocket ds=new DatagramSocket(20000);

        DatagramPacket dps=new DatagramPacket(bufs,bufs.length,ia,port);;


        Thread recThread=new Thread(new RecRun(ds));
        Thread sendThread=new Thread(new SendRun(ds,dps));

        recThread.start();
        sendThread.start();
    }
}

TCP

tcp分客戶端和服務端
客戶端對應的對象是Socket
服務端對應的對象是ServerSocket

客戶端
通過查閱Socket對象,發現在該對象建立時,就可以去連接指定主機
因爲tcp是面向連接的,所以在建立socket服務時,就要有服務端存在,並連接成功,形成通路後,在該通道進行數據傳輸。

TCP服務端

import java.net.*;
import java.io.*;

class TcpServer
{
    public static void main(String[] args) throws Exception
    {

        //創建一個服務端socket,綁定本機端口20000
        ServerSocket mySocket=new ServerSocket(20000);

        //通過accept方法獲取連接過來的客戶端對象
        Socket cSocket=mySocket.accept();
        //獲取客戶端發送過來的數據,那麼要使用客戶端對象的讀取流來讀取數據

        String ip=cSocket.getInetAddress().getHostAddress();
        System.out.println(ip+"已連接");

        InputStream in=cSocket.getInputStream();

        byte[] buf=new byte[1024];
        int len=in.read(buf);
        String data=new String(buf,0,len);

        System.out.println(data);

        //關閉客戶端

        cSocket.close();

        mySocket.close();

    }
}

TCP客戶端

import java.net.*;
import java.io.*;

class TcpClient
{
    public static void main(String[] args) throws Exception
    {
        //創建客戶端的socket服務,指定目的主機和端口
        Socket cSocket=new Socket("192.168.0.104",20000);
        OutputStream out=cSocket.getOutputStream();
        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
        String str=bufr.readLine();
        out.write(str.getBytes());

        cSocket.close();
    }
}

TCP阻塞式聊天

1.服務器啓動,等待客戶端連接
2.客戶端連接,然後等待用戶輸入
3.用戶輸入信息,回車發送,客戶端進入等待,等待服務器發送信息
4.服務器接受消息,並顯示
5.服務器進入阻塞狀態,等待用戶輸入信息
6.服務器發送信息給客戶端
7.服務器進入等待,客戶端收到信息並顯示.

import java.io.*;
import java.net.*;

class TcpChatServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket sSocket=new ServerSocket(20000);
        Socket cSocket=sSocket.accept();
        String ip=cSocket.getInetAddress().getHostAddress();
        System.out.println(ip+"已連接");
        //鍵盤輸入流
        BufferedReader kBufR=
            new BufferedReader(new InputStreamReader(System.in));
        //網絡輸入流
        BufferedReader bufR=
            new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
        //網絡輸出流
        BufferedWriter bufW=
            new BufferedWriter(new OutputStreamWriter(cSocket.getOutputStream()));
        String line;
        String lineInput;

        while((line=bufR.readLine())!=null)
        {
            if(line.equals("over"))
                break;
            System.out.println(ip+": "+line);
            lineInput=kBufR.readLine();
            bufW.write(lineInput);
            bufW.newLine();
            bufW.flush();


        }
        kBufR.close();
        cSocket.close();
        sSocket.close();
    }
}
class TcpChatClient
{
    public static void main(String[] args) throws Exception
    {
        Socket cSocket=new Socket("192.168.0.104",20000);
        //鍵盤輸入流
        BufferedReader kBufR=
            new BufferedReader(new InputStreamReader(System.in));
        //網絡輸入流
        BufferedReader bufR=
            new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
        //網絡輸出流
        BufferedWriter bufW=
            new BufferedWriter(new OutputStreamWriter(cSocket.getOutputStream()));

        String line;
        String data;
        while((line=kBufR.readLine())!=null)
        {
            if(line.equals("over"))
                break;
            bufW.write(line);
            bufW.newLine();
            bufW.flush();
            data=bufR.readLine();
            System.out.println("服務器說:"+data);
        }
        kBufR.close();
        cSocket.close();

    }

}

URL

URL(String spec)
根據 String 表示形式創建 URL 對象。

String getFile()
獲取此 URL 的文件名。
String getHost()
獲取此 URL 的主機名(如果適用)。
String getPath()
獲取此 URL 的路徑部分。
int getPort()
獲取此 URL 的端口號。
String getProtocol()
獲取此 URL 的協議名稱。
String getQuery()
獲取此 URL 的查詢部分。
URLConnection openConnection()
返回一個 URLConnection 對象,它表示到 URL 所引用的遠程對象的連接。

URLConnection

直接已知子類:
HttpURLConnection, JarURLConnection
InputStream getInputStream()
返回從此打開的連接讀取的輸入流。
OutputStream getOutputStream()
返回寫入到此連接的輸出流。
通過流對象可以像socket一樣進行http通訊
通過getInputStream獲取輸入流可以從服務器獲得網頁源文件

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章