[学习笔记]Java网络编程之TCP通讯

1. Socket类

1.1 概述

用于创建客户端套接字,以此建立TCP链接。

1.2 构造器

  • Socket()
  • Socket(InetAddress address, int port)
  • Socket(String host, int port)
  • Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
  • Socket(String host, int port, InetAddress localAddr, int localPort)

1.3 常用方法

  • 将指定本地地址绑定到套接字

    void  bind(SocketAddress bindpoint)

  • 关闭该套接字

    void  close()

  • 将套接字连接到服务器

    void  connect(SocketAddress endpoint)

    void  connect(SocketAddress endpoint, int timeout)

  • 获取该套接字连接的远程地址或端口号

    InetAddress  getInetAddress()

    int  getPort()

    SocketAddress  getRemoteSocketAddress()

  • 获取该套接字内的输入流或输出流

    InputStream  getInputStream()

    OutputStream  getOutputStream()

  • 判断或设置连接是否保持活动

    boolean  getKeepAlive()

    void  setKeepAlive(boolean on)

  • 获取该套接字绑定的本地地址和端口号

    InetAddress  getLocalAddress()

    int  getLocalPort()

    SocketAddress  getLocalSocketAddress()

  • 获取发送或接收缓冲区大小

    int  getSendBufferSize()

    int  getReceiveBufferSize()

  • 设置缓冲区大小

    void  setReceiveBufferSize(int size)

    void  setSendBufferSize(int size)

  • 判断套接字状态

    boolean  isBound()

    boolean  isClosed()

    boolean  isConnected()

    boolean  isInputShutdown()

    boolean  isOutputShutdown()

  • 设置套接字输入输出流的结束标志

    void  shutdownInput()

    void  shutdownOutput()

2. ServerSocket类

2.1 概述

用于创建服务端套接字,用于监听TCP连接。

2.2 构造器

  • ServerSocket()
  • ServerSocket(int port)
  • ServerSocket(int port, int backlog)
  • ServerSocket(int port, int backlog, InetAddress bindAddr)

2.3 常用方法

  • 监听与服务端连接的套接字,并获取该套接字。

    Socket  accept()

  • 将该套接字绑定到本地地址

    void  bind(SocketAddress endpoint)

    void  bind(SocketAddress endpoint, int backlog)

  • 关闭该套接字

    void  close()

  • 获取该套接字绑定的本地地址或监听端口

    InetAddress  getInetAddress()

    int  getLocalPort()

    SocketAddress  getLocalSocketAddress()

  • 获取和设定接收缓冲区大小

    int  getReceiveBufferSize()

    void  setReceiveBufferSize(int size)

  • 判断该套接字的状态

    boolean  isBound()

    boolean  isClosed()

  • 设置连接超时时间

    void  setSoTimeout(int timeout)

3. 通信步骤

客户端

  • 创建客户端套接字,明确服务端地址和端口号。
  • 通信建立后获取该套接字内的输入输出流。
  • 通过输出流发送数据,通过输入流接收数据。
  • 关闭套接字。

服务端

  • 创建服务端套接字,明确本地地址和端口号。
  • 监听连接,获取已连接客户端的套接字。
  • 通过输出流发送数据,通过输入流接收数据。
  • 关闭套接字连接。
  • 关闭服务端套接字(一般情况下不关闭而循环监听)。

4. 示例

客户端


package net.tcp;

 

import java.io.IOException;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class TCP_Client {

 

  public static void main(String[] args) throws UnknownHostException, IOException {

    /*

     * TCP客户端

     */

    System.out.println( "TCP客户端");

    InetAddress ip = InetAddress.getLocalHost();

   

    // 1. 建立TCP的客户端socket,明确服务端的地址和端口。

    Socket s = new Socket( ip, 10003);

 

    // 2. 如果通道建立成功,则自动生成Socket IO流。

    // 客户端需要获取socket流的中输出流将数据发送到服务端

    OutputStream out = s.getOutputStream();

 

    // 3. 通过socket输出流将数据发送。

    out.write("hello tcp".getBytes());

 

    // 4. 关闭资源。

    s.close();

  }

}

服务端


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.net.ServerSocket;

import java.net.Socket;

 

public class TCP_Server {

 

  public static void main(String[] args) throws IOException {

    /*

     * TCP服务器端

     */

    System.out.println( "TCP服务器端" );

 

    // 1. 创建服务端的socket,监听一个端口。

    ServerSocket ss = new ServerSocket(10003);

 

    while ( true) {

      // 2. 服务端只要获取到连接过来的客户端套接字就可以和指定的客户端通信了

      Socket s = ss.accept();   // 阻塞,监听链接

      String ip = s.getRemoteSocketAddress().toString();

     

      System.out.println( ip + " is connected!");

      // 3. 通过获取的套接字,读取IO流中客户端发来的数据

      InputStream in = s.getInputStream();

 

      // 4. 获取数据并显示

      byte[] buf = new byte[1024];

      int len = in.read(buf);

      String text = new String( buf, 0, len);

      if ("close".equals( text)) {

        s.close();

        break;

      }

      System.out.println( text);

 

      // 5. 关闭资源。

      s.close();

 

    }

    ss.close();

  }

}

统一资源定位符URL

1. 概述

如同在网络上的门牌,是因特网上标准的资源的地址。

2. 格式

协议类型://服务器地址(必要时需加上端口号)/路径/文件名

其中包括

  • 传送协议
  • 服务器
  • 端口号(以数字方式表示,若为HTTP的默认值“:80”可省略)
  • 路径(以“/”字符区别路径中的每一个目录名称)
  • 查询(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF-8的URL编码,避开字符冲突的问题)

例如:https://www.google.com.hk:443/search?hl=zh-CN&q=URL,其中:

  • https:协议
  • www.google.com.hk:服务器
  • 443:端口号
  • search:路径
  • ?hl=zh-CN&q=URL:查询

3. URL类

3.1 概述

用于直接使用URL连接服务器。

3.2 构造器

  • URL(String spec)
  • URL(String protocol, String host, int port, String file)
  • URL(String protocol, String host, String file)

3.3 常用方法

  • 获取该URL所关联的协议的默认端口号

    int  getDefaultPort()

  • 获取该URL的属性

    String  getFile()

    String  getHost()

    String  getPath()

    int  getPort()

    String  getProtocol()

    String  getQuery()

  • 获取该URL连接的资源连接对象(套接字)

    URLConnection  openConnection()

  • 获取该URL连接的输入流

    InputStream  openStream()

4. URLConnection类

4.1 概述

用于获取URL连接所获取的流及其他信息。

4.2 构造器

  • URLConnection(URL url)

4.3 常用方法

  • 获取和设置连接超时时间

    int  getConnectTimeout()

    void  setConnectTimeout(int timeout)

  • 获取内置输入流和输出流

    InputStream  getInputStream()

    OutputStream  getOutputStream()

  • 获取与其绑定的URL

    URL  getURL()

5. 示例


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.URL;

import java.net.URLConnection;

import java.net.UnknownHostException;

 

public class WebBrowserByURL {

 

  /**

   * @param args

   * @throws IOException

   * @throws UnknownHostException

   */

  public static void main(String[] args) throws UnknownHostException, IOException {

 

    /*

     * 模拟一个浏览器

     */

    URL url = new URL("https://www.google.com.hk:443/search?hl=zh-CN&q=URL" );

 

    System.out.println( "getProtocol: " + url.getProtocol());

    System.out.println( "getHost: " + url .getHost());

    System.out.println( "getPort: " + url .getPort());

    System.out.println( "getPath: " + url .getPath());

    System.out.println( "getFile: " + url .getFile());

    System.out.println( "getQuery: " + url .getQuery());

 

    // 获取指定资源连接对象,其中封装了Socket

    URLConnection uc = url.openConnection();

    BufferedReader br = new BufferedReader( new InputStreamReader(uc.getInputStream(), "utf-8" ));

    String str = null;

    while (( str = br.readLine()) != null) {

      System.out.println( str);

    }

  }

}

运行结果(没有连接成功,大家都懂的)

getProtocol: https

getHost: www.google.com.hk

getPort: 443

getPath: /search

getFile: /search?hl=zh-CN&q=URL

getQuery: hl=zh-CN&q=URL

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">

<TITLE>302 Moved</TITLE></HEAD><BODY>

<H1>302 Moved</H1>

The document has moved

<A HREF="http://www.google.com.hk/url?sa=p&amp;hl=zh-CN&amp;pref=hkredirect&amp;pval=yes&amp;q=http://www.google.com.hk/search%3Fhl%3Dzh-CN%26q%3DURL%26gws_rd%3Dcr&amp;ust=1419135282781986&amp;usg=AFQjCNEL7CpZx_cu6Udk4yn66P0udI_pdA">here</A>.

</BODY></HTML>

案例

1. 客户端发送数据,服务端将数据大写后返回

客户端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.net.InetAddress;

import java.net.Socket;

 

public class Test_UpperCaseByTCP_Client {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "客户端启动..." );

 

    // 确定服务器地址

    InetAddress ip = InetAddress.getLocalHost();

 

    // 2. 创建套接字

    Socket s = new Socket( ip, 10001);

 

    /*

     * 3. 发送:

     * 源:键盘录入

     * 目的:Socket流,类型:OutputStream

     */

    BufferedReader brSend = new BufferedReader( new InputStreamReader(System.in ));

    // BufferedWriter bwSend = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

   

    // 输出流可使用PrintStream,可以自动添加换行和自动刷新,更加方便

    PrintStream psSend = new PrintStream(s.getOutputStream(), true);

 

    /*

     * 4. 接收: 源:Socket流 目的:屏幕显示

     */

    BufferedReader brRece = new BufferedReader( new InputStreamReader(s.getInputStream()));

 

    // 5. 发送,并显示响应数据

    String str = null;

    while (( str = brSend.readLine()) != null) {

      // bwSend.write(str);

      // bwSend.newLine();

      // bwSend.flush();

      psSend.println( str);

 

      if ("exit".equals( str) || "close".equals(str )) {

        break;

      }

 

      str = brRece.readLine();

      System.out.println( str);

    }

 

    // 6. 关闭资源

    s.close();

  }

}

服务端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.net.ServerSocket;

import java.net.Socket;

 

public class Test_UpperCaseByTCP_Server {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "服务端启动..." );

 

    // 1. 创建套接字

    ServerSocket ss = new ServerSocket(10001);

 

    while ( true) {

      // 2. 获取客户端套接字

      Socket s = ss.accept();

 

      System.out.println(s .getInetAddress().getHostAddress() + "已连接!" );

 

      // 3. 明确接收和发送的Socket流

      BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream()));

      // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

 

      // 输出流可使用PrintStream,可以自动添加换行和自动刷新,更加方便

      PrintStream ps = new PrintStream(s.getOutputStream(), true);

 

      // 4. 获取数据并做大写转换

      String str = null;

      while (( str = br.readLine()) != null) {

        if ( "exit".equals(str )) {

          break;

        } else if ( "close".equals(str )) {

          System.out.println(s .getInetAddress().getHostAddress() + ":" + s .getPort()

              + " 请求关闭服务端..." );

          s.close();

          ss.close();

          System. out.println("服务端已关闭!" );

          return;

        }

        System. out.println("数据:" + str );

 

        // 5. 将转换好的数据发送回客户端

        // bw.write(str.toUpperCase());

        // bw.newLine();

        // bw.flush();

        ps.println( str.toUpperCase());

      }

      // 6. 关闭客户端

      s.close();

    }

  }

}

运行结果

客户端

客户端启动...

java

JAVA

it

IT

close

服务端

192.168.1.22已连接!

数据:java

数据:it

192.168.1.22:7755 请求关闭服务端...

服务端已关闭!

2. 文件上传服务

客户端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.Socket;

 

public class Test_UploadByTCP_Client {

 

  private static final int BUFFER_SIZE = 8192;

 

  public static void main(String[] args) throws IOException {

    System.out.println( "上传客户端启动..." );

   

    // 1. 获取服务器地址和端口

    InetAddress ip = InetAddress.getLocalHost();

   

    // 2. 创建套接字连接服务器

    Socket s = new Socket( ip, 10002);

   

    /*

     * 3. 发送:

     * 源:文件

     * 目的:Socket流,类型:OutputStream

     */

    File file = new File( "temp\\byte.ape");

    FileInputStream fis = new FileInputStream( file);

    OutputStream os = s.getOutputStream();

   

    // 4. 循环发送

    byte[] buf = new byte[ BUFFER_SIZE];

    int len = 0;

    while (( len = fis.read( buf)) != -1) {

      os.write(buf, 0, len);

    }

    fis.close();

   

    // 5. 发送结束标志

    s.shutdownOutput();

   

    // 6. 读取服务器反馈信息

    BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream()));

    System.out.println( br.readLine());

   

    // 7. 关闭资源

    s.close();

  }

}

服务端

Test_UploadByTCP.java


package net.tcp;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class Test_UploadByTCP implements Runnable {

 

  private static final int BUFFER_SIZE = 8192;

  private Socket s;

 

  public Test_UploadByTCP(Socket s) {

    super();

    this.s = s;

  }

 

  @Override

  public void run() {

    /*

     * 1. 接收: 源:Socket流

     * 目的:文件

     */

   

    File path = new File( "temp\\" + s.getInetAddress().getHostAddress());

    if (!path.exists()) {

      path.mkdirs();

    }

   

    // 对上传文件按上传时间命名,并避免与已有文件名重复

    Date date = new Date();

    SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd-HHmmss-" );

    String preName = sdf.format(date);

    int count = 0;

    File file = new File( path, preName + count + ".ape");

    while ( file.exists()) {

      count++;

      file = new File( path, preName + count + ".ape");

    }

 

    try {

      InputStream is = s.getInputStream();

      FileOutputStream fos = new FileOutputStream( file);

 

      // 2. 循环接收

      byte[] buf = new byte[ BUFFER_SIZE];

      int len = 0;

      while (( len = is.read( buf)) != -1) {

        fos.write( buf, 0, len);

      }

      fos.close();

 

      String msg = "上传成功!";

      // 4. 发送反馈信息

      OutputStream os = s.getOutputStream();

      os.write(msg.getBytes());

     

      // 5. 关闭资源

      s.close();

 

    } catch (IOException e) {

      e.printStackTrace();

    }

  }

}

Test_UploadByTCP_Server.java


package net.tcp;

 

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

 

public class Test_UploadByTCP_Server {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "上传服务端启动..." );

   

    // 1. 创建套接字

    ServerSocket ss = new ServerSocket(10002);

    while ( true) {

      // 2. 获取客户端套接字

      Socket s = ss.accept();

     

      // 3. 创建线程完成文件上传

      new Thread( new Test_UploadByTCP( s)).start();

    }

  }

}

3. 浏览器和Web服务器模拟

浏览器模拟


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.net.InetAddress;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class WebBrowser {

 

  /**

   * @param args

   * @throws IOException

   * @throws UnknownHostException

   */

  public static void main(String[] args) throws UnknownHostException, IOException {

 

    /*

     * 模拟一个浏览器

     */

    InetAddress ip = InetAddress.getByName("www.itheima.com");

    System.out.println( ip.getHostAddress());

    Socket s = new Socket( ip, 80);

   

    // 浏览器请求信息发送给服务端

    PrintWriter out = new PrintWriter(s.getOutputStream(), true);

    out.println("GET / HTTP/1.1");

    out.println("Accept: */*");

    out.println("Host: www.itheima.com:80");

    out.println("Connection: close");

    out.println(); // 空行。

 

    // 读取服务端的数据。

    InputStream in = s.getInputStream();

    byte[] buf = new byte[1024];

    int len = in.read(buf);

    String text = new String( buf, 0, len, "utf-8");

    System.out.println( text);

 

    s.close();

  }

}

Web服务器模拟


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

 

public class WebServer {

 

  public static void main(String[] args) throws IOException {

    /*

     * 自定义Web服务端 获取浏览器的信息,并反馈 Html信息。

     */

    System.out.println( "自定义Web服务器启动..." );

    ServerSocket ss = new ServerSocket(9090);

 

    Socket s = ss.accept();

    System.out.println(s .getInetAddress().getHostAddress() + " is connected.");

 

    // 读取客户端的数据。

    InputStream in = s.getInputStream();

    byte[] buf = new byte[1024];

    int len = in.read(buf);

    String text = new String( buf, 0, len);

    System.out.println( text);

 

    // 给客户端回馈数据。

    PrintWriter out = new PrintWriter(s.getOutputStream(), true);

    out.println("<font color=‘red‘ size=‘7‘>欢迎光临</font>" );

 

    s.close();

    ss.close();

  }

}

1. Socket类

1.1 概述

用于创建客户端套接字,以此建立TCP链接。

1.2 构造器

  • Socket()
  • Socket(InetAddress address, int port)
  • Socket(String host, int port)
  • Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
  • Socket(String host, int port, InetAddress localAddr, int localPort)

1.3 常用方法

  • 将指定本地地址绑定到套接字

    void  bind(SocketAddress bindpoint)

  • 关闭该套接字

    void  close()

  • 将套接字连接到服务器

    void  connect(SocketAddress endpoint)

    void  connect(SocketAddress endpoint, int timeout)

  • 获取该套接字连接的远程地址或端口号

    InetAddress  getInetAddress()

    int  getPort()

    SocketAddress  getRemoteSocketAddress()

  • 获取该套接字内的输入流或输出流

    InputStream  getInputStream()

    OutputStream  getOutputStream()

  • 判断或设置连接是否保持活动

    boolean  getKeepAlive()

    void  setKeepAlive(boolean on)

  • 获取该套接字绑定的本地地址和端口号

    InetAddress  getLocalAddress()

    int  getLocalPort()

    SocketAddress  getLocalSocketAddress()

  • 获取发送或接收缓冲区大小

    int  getSendBufferSize()

    int  getReceiveBufferSize()

  • 设置缓冲区大小

    void  setReceiveBufferSize(int size)

    void  setSendBufferSize(int size)

  • 判断套接字状态

    boolean  isBound()

    boolean  isClosed()

    boolean  isConnected()

    boolean  isInputShutdown()

    boolean  isOutputShutdown()

  • 设置套接字输入输出流的结束标志

    void  shutdownInput()

    void  shutdownOutput()

2. ServerSocket类

2.1 概述

用于创建服务端套接字,用于监听TCP连接。

2.2 构造器

  • ServerSocket()
  • ServerSocket(int port)
  • ServerSocket(int port, int backlog)
  • ServerSocket(int port, int backlog, InetAddress bindAddr)

2.3 常用方法

  • 监听与服务端连接的套接字,并获取该套接字。

    Socket  accept()

  • 将该套接字绑定到本地地址

    void  bind(SocketAddress endpoint)

    void  bind(SocketAddress endpoint, int backlog)

  • 关闭该套接字

    void  close()

  • 获取该套接字绑定的本地地址或监听端口

    InetAddress  getInetAddress()

    int  getLocalPort()

    SocketAddress  getLocalSocketAddress()

  • 获取和设定接收缓冲区大小

    int  getReceiveBufferSize()

    void  setReceiveBufferSize(int size)

  • 判断该套接字的状态

    boolean  isBound()

    boolean  isClosed()

  • 设置连接超时时间

    void  setSoTimeout(int timeout)

3. 通信步骤

客户端

  • 创建客户端套接字,明确服务端地址和端口号。
  • 通信建立后获取该套接字内的输入输出流。
  • 通过输出流发送数据,通过输入流接收数据。
  • 关闭套接字。

服务端

  • 创建服务端套接字,明确本地地址和端口号。
  • 监听连接,获取已连接客户端的套接字。
  • 通过输出流发送数据,通过输入流接收数据。
  • 关闭套接字连接。
  • 关闭服务端套接字(一般情况下不关闭而循环监听)。

4. 示例

客户端


package net.tcp;

 

import java.io.IOException;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class TCP_Client {

 

  public static void main(String[] args) throws UnknownHostException, IOException {

    /*

     * TCP客户端

     */

    System.out.println( "TCP客户端");

    InetAddress ip = InetAddress.getLocalHost();

   

    // 1. 建立TCP的客户端socket,明确服务端的地址和端口。

    Socket s = new Socket( ip, 10003);

 

    // 2. 如果通道建立成功,则自动生成Socket IO流。

    // 客户端需要获取socket流的中输出流将数据发送到服务端

    OutputStream out = s.getOutputStream();

 

    // 3. 通过socket输出流将数据发送。

    out.write("hello tcp".getBytes());

 

    // 4. 关闭资源。

    s.close();

  }

}

服务端


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.net.ServerSocket;

import java.net.Socket;

 

public class TCP_Server {

 

  public static void main(String[] args) throws IOException {

    /*

     * TCP服务器端

     */

    System.out.println( "TCP服务器端" );

 

    // 1. 创建服务端的socket,监听一个端口。

    ServerSocket ss = new ServerSocket(10003);

 

    while ( true) {

      // 2. 服务端只要获取到连接过来的客户端套接字就可以和指定的客户端通信了

      Socket s = ss.accept();   // 阻塞,监听链接

      String ip = s.getRemoteSocketAddress().toString();

     

      System.out.println( ip + " is connected!");

      // 3. 通过获取的套接字,读取IO流中客户端发来的数据

      InputStream in = s.getInputStream();

 

      // 4. 获取数据并显示

      byte[] buf = new byte[1024];

      int len = in.read(buf);

      String text = new String( buf, 0, len);

      if ("close".equals( text)) {

        s.close();

        break;

      }

      System.out.println( text);

 

      // 5. 关闭资源。

      s.close();

 

    }

    ss.close();

  }

}

统一资源定位符URL

1. 概述

如同在网络上的门牌,是因特网上标准的资源的地址。

2. 格式

协议类型://服务器地址(必要时需加上端口号)/路径/文件名

其中包括

  • 传送协议
  • 服务器
  • 端口号(以数字方式表示,若为HTTP的默认值“:80”可省略)
  • 路径(以“/”字符区别路径中的每一个目录名称)
  • 查询(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF-8的URL编码,避开字符冲突的问题)

例如:https://www.google.com.hk:443/search?hl=zh-CN&q=URL,其中:

  • https:协议
  • www.google.com.hk:服务器
  • 443:端口号
  • search:路径
  • ?hl=zh-CN&q=URL:查询

3. URL类

3.1 概述

用于直接使用URL连接服务器。

3.2 构造器

  • URL(String spec)
  • URL(String protocol, String host, int port, String file)
  • URL(String protocol, String host, String file)

3.3 常用方法

  • 获取该URL所关联的协议的默认端口号

    int  getDefaultPort()

  • 获取该URL的属性

    String  getFile()

    String  getHost()

    String  getPath()

    int  getPort()

    String  getProtocol()

    String  getQuery()

  • 获取该URL连接的资源连接对象(套接字)

    URLConnection  openConnection()

  • 获取该URL连接的输入流

    InputStream  openStream()

4. URLConnection类

4.1 概述

用于获取URL连接所获取的流及其他信息。

4.2 构造器

  • URLConnection(URL url)

4.3 常用方法

  • 获取和设置连接超时时间

    int  getConnectTimeout()

    void  setConnectTimeout(int timeout)

  • 获取内置输入流和输出流

    InputStream  getInputStream()

    OutputStream  getOutputStream()

  • 获取与其绑定的URL

    URL  getURL()

5. 示例


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.URL;

import java.net.URLConnection;

import java.net.UnknownHostException;

 

public class WebBrowserByURL {

 

  /**

   * @param args

   * @throws IOException

   * @throws UnknownHostException

   */

  public static void main(String[] args) throws UnknownHostException, IOException {

 

    /*

     * 模拟一个浏览器

     */

    URL url = new URL("https://www.google.com.hk:443/search?hl=zh-CN&q=URL" );

 

    System.out.println( "getProtocol: " + url.getProtocol());

    System.out.println( "getHost: " + url .getHost());

    System.out.println( "getPort: " + url .getPort());

    System.out.println( "getPath: " + url .getPath());

    System.out.println( "getFile: " + url .getFile());

    System.out.println( "getQuery: " + url .getQuery());

 

    // 获取指定资源连接对象,其中封装了Socket

    URLConnection uc = url.openConnection();

    BufferedReader br = new BufferedReader( new InputStreamReader(uc.getInputStream(), "utf-8" ));

    String str = null;

    while (( str = br.readLine()) != null) {

      System.out.println( str);

    }

  }

}

运行结果(没有连接成功,大家都懂的)

getProtocol: https

getHost: www.google.com.hk

getPort: 443

getPath: /search

getFile: /search?hl=zh-CN&q=URL

getQuery: hl=zh-CN&q=URL

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">

<TITLE>302 Moved</TITLE></HEAD><BODY>

<H1>302 Moved</H1>

The document has moved

<A HREF="http://www.google.com.hk/url?sa=p&amp;hl=zh-CN&amp;pref=hkredirect&amp;pval=yes&amp;q=http://www.google.com.hk/search%3Fhl%3Dzh-CN%26q%3DURL%26gws_rd%3Dcr&amp;ust=1419135282781986&amp;usg=AFQjCNEL7CpZx_cu6Udk4yn66P0udI_pdA">here</A>.

</BODY></HTML>

案例

1. 客户端发送数据,服务端将数据大写后返回

客户端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.net.InetAddress;

import java.net.Socket;

 

public class Test_UpperCaseByTCP_Client {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "客户端启动..." );

 

    // 确定服务器地址

    InetAddress ip = InetAddress.getLocalHost();

 

    // 2. 创建套接字

    Socket s = new Socket( ip, 10001);

 

    /*

     * 3. 发送:

     * 源:键盘录入

     * 目的:Socket流,类型:OutputStream

     */

    BufferedReader brSend = new BufferedReader( new InputStreamReader(System.in ));

    // BufferedWriter bwSend = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

   

    // 输出流可使用PrintStream,可以自动添加换行和自动刷新,更加方便

    PrintStream psSend = new PrintStream(s.getOutputStream(), true);

 

    /*

     * 4. 接收: 源:Socket流 目的:屏幕显示

     */

    BufferedReader brRece = new BufferedReader( new InputStreamReader(s.getInputStream()));

 

    // 5. 发送,并显示响应数据

    String str = null;

    while (( str = brSend.readLine()) != null) {

      // bwSend.write(str);

      // bwSend.newLine();

      // bwSend.flush();

      psSend.println( str);

 

      if ("exit".equals( str) || "close".equals(str )) {

        break;

      }

 

      str = brRece.readLine();

      System.out.println( str);

    }

 

    // 6. 关闭资源

    s.close();

  }

}

服务端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.net.ServerSocket;

import java.net.Socket;

 

public class Test_UpperCaseByTCP_Server {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "服务端启动..." );

 

    // 1. 创建套接字

    ServerSocket ss = new ServerSocket(10001);

 

    while ( true) {

      // 2. 获取客户端套接字

      Socket s = ss.accept();

 

      System.out.println(s .getInetAddress().getHostAddress() + "已连接!" );

 

      // 3. 明确接收和发送的Socket流

      BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream()));

      // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

 

      // 输出流可使用PrintStream,可以自动添加换行和自动刷新,更加方便

      PrintStream ps = new PrintStream(s.getOutputStream(), true);

 

      // 4. 获取数据并做大写转换

      String str = null;

      while (( str = br.readLine()) != null) {

        if ( "exit".equals(str )) {

          break;

        } else if ( "close".equals(str )) {

          System.out.println(s .getInetAddress().getHostAddress() + ":" + s .getPort()

              + " 请求关闭服务端..." );

          s.close();

          ss.close();

          System. out.println("服务端已关闭!" );

          return;

        }

        System. out.println("数据:" + str );

 

        // 5. 将转换好的数据发送回客户端

        // bw.write(str.toUpperCase());

        // bw.newLine();

        // bw.flush();

        ps.println( str.toUpperCase());

      }

      // 6. 关闭客户端

      s.close();

    }

  }

}

运行结果

客户端

客户端启动...

java

JAVA

it

IT

close

服务端

192.168.1.22已连接!

数据:java

数据:it

192.168.1.22:7755 请求关闭服务端...

服务端已关闭!

2. 文件上传服务

客户端


package net.tcp;

 

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.Socket;

 

public class Test_UploadByTCP_Client {

 

  private static final int BUFFER_SIZE = 8192;

 

  public static void main(String[] args) throws IOException {

    System.out.println( "上传客户端启动..." );

   

    // 1. 获取服务器地址和端口

    InetAddress ip = InetAddress.getLocalHost();

   

    // 2. 创建套接字连接服务器

    Socket s = new Socket( ip, 10002);

   

    /*

     * 3. 发送:

     * 源:文件

     * 目的:Socket流,类型:OutputStream

     */

    File file = new File( "temp\\byte.ape");

    FileInputStream fis = new FileInputStream( file);

    OutputStream os = s.getOutputStream();

   

    // 4. 循环发送

    byte[] buf = new byte[ BUFFER_SIZE];

    int len = 0;

    while (( len = fis.read( buf)) != -1) {

      os.write(buf, 0, len);

    }

    fis.close();

   

    // 5. 发送结束标志

    s.shutdownOutput();

   

    // 6. 读取服务器反馈信息

    BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream()));

    System.out.println( br.readLine());

   

    // 7. 关闭资源

    s.close();

  }

}

服务端

Test_UploadByTCP.java


package net.tcp;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.Socket;

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class Test_UploadByTCP implements Runnable {

 

  private static final int BUFFER_SIZE = 8192;

  private Socket s;

 

  public Test_UploadByTCP(Socket s) {

    super();

    this.s = s;

  }

 

  @Override

  public void run() {

    /*

     * 1. 接收: 源:Socket流

     * 目的:文件

     */

   

    File path = new File( "temp\\" + s.getInetAddress().getHostAddress());

    if (!path.exists()) {

      path.mkdirs();

    }

   

    // 对上传文件按上传时间命名,并避免与已有文件名重复

    Date date = new Date();

    SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd-HHmmss-" );

    String preName = sdf.format(date);

    int count = 0;

    File file = new File( path, preName + count + ".ape");

    while ( file.exists()) {

      count++;

      file = new File( path, preName + count + ".ape");

    }

 

    try {

      InputStream is = s.getInputStream();

      FileOutputStream fos = new FileOutputStream( file);

 

      // 2. 循环接收

      byte[] buf = new byte[ BUFFER_SIZE];

      int len = 0;

      while (( len = is.read( buf)) != -1) {

        fos.write( buf, 0, len);

      }

      fos.close();

 

      String msg = "上传成功!";

      // 4. 发送反馈信息

      OutputStream os = s.getOutputStream();

      os.write(msg.getBytes());

     

      // 5. 关闭资源

      s.close();

 

    } catch (IOException e) {

      e.printStackTrace();

    }

  }

}

Test_UploadByTCP_Server.java


package net.tcp;

 

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

 

public class Test_UploadByTCP_Server {

 

  public static void main(String[] args) throws IOException {

    System.out.println( "上传服务端启动..." );

   

    // 1. 创建套接字

    ServerSocket ss = new ServerSocket(10002);

    while ( true) {

      // 2. 获取客户端套接字

      Socket s = ss.accept();

     

      // 3. 创建线程完成文件上传

      new Thread( new Test_UploadByTCP( s)).start();

    }

  }

}

3. 浏览器和Web服务器模拟

浏览器模拟


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.net.InetAddress;

import java.net.Socket;

import java.net.UnknownHostException;

 

public class WebBrowser {

 

  /**

   * @param args

   * @throws IOException

   * @throws UnknownHostException

   */

  public static void main(String[] args) throws UnknownHostException, IOException {

 

    /*

     * 模拟一个浏览器

     */

    InetAddress ip = InetAddress.getByName("www.itheima.com");

    System.out.println( ip.getHostAddress());

    Socket s = new Socket( ip, 80);

   

    // 浏览器请求信息发送给服务端

    PrintWriter out = new PrintWriter(s.getOutputStream(), true);

    out.println("GET / HTTP/1.1");

    out.println("Accept: */*");

    out.println("Host: www.itheima.com:80");

    out.println("Connection: close");

    out.println(); // 空行。

 

    // 读取服务端的数据。

    InputStream in = s.getInputStream();

    byte[] buf = new byte[1024];

    int len = in.read(buf);

    String text = new String( buf, 0, len, "utf-8");

    System.out.println( text);

 

    s.close();

  }

}

Web服务器模拟


package net.tcp;

 

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

 

public class WebServer {

 

  public static void main(String[] args) throws IOException {

    /*

     * 自定义Web服务端 获取浏览器的信息,并反馈 Html信息。

     */

    System.out.println( "自定义Web服务器启动..." );

    ServerSocket ss = new ServerSocket(9090);

 

    Socket s = ss.accept();

    System.out.println(s .getInetAddress().getHostAddress() + " is connected.");

 

    // 读取客户端的数据。

    InputStream in = s.getInputStream();

    byte[] buf = new byte[1024];

    int len = in.read(buf);

    String text = new String( buf, 0, len);

    System.out.println( text);

 

    // 给客户端回馈数据。

    PrintWriter out = new PrintWriter(s.getOutputStream(), true);

    out.println("<font color=‘red‘ size=‘7‘>欢迎光临</font>" );

 

    s.close();

    ss.close();

  }

}
时间: 2024-10-19 00:56:18

[学习笔记]Java网络编程之TCP通讯的相关文章

[学习笔记]Java网络编程之UDP通讯

1. 体系结构 计算机网络各层及其协议的集合,称为网络的体系结构.目前公认的计算机网络体系结构有概念清楚理论完善的OSI七层协议结构和实际上广泛应用的TCP/IP四层体系结构. 2. 各层概述 应用层:直接为用户的程序提供服务,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等. 运输层:负责向两个主机中进程之间的通信提供服务,主要使用面向连接的TCP协议和无连接的UDP协议. 网络层:负责为分组交换网上不同主机提供地址交付的通信服务,该层使用IP协议,所以在该层传送的数据称之为IP数

java网络编程之TCP实例

Dgram类 package Socket; import java.net.DatagramPacket; import java.net.InetAddress; public class Dgram { public static DatagramPacket toDatagram(String s, InetAddress destIA, int destPort) { byte[] buf = new byte[s.length() + 1]; s.getBytes(0, s.leng

Java网络编程之TCP、UDP

Java网络编程提供了两种协议:TCP(传输控制协议)和UDP(数据报协议).TCP(Transmission Control Protocol)是一种可靠的传输协议,传输时会采用"三次握手"端的方式建立连接,以保证数据的可靠性和安全性:而UDP(User Datagram Protocol)协议是一种不可靠的传输协议,发送的数据不一定能够接受的到,网上的聊天是工具一般采用的此协议.下面将详细的接受TCP和UDP的使用以及相应的编码. 一.TCP网络通信 Java中使用Socket(套

Java网络编程之TCP通信

一.概述 Socket类是Java运行clientTCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信. Socket类的方法会建立和销毁连接,设置各种Socket选项. ServerSocket类是Java执行server端操作的基础类,该类执行于server,监听入站TCP连接.每一个socketserver监听server的某个port.当远程主机的client尝试连接此port时.server就被唤醒.并返回一个表示两台主机之间socket的正常Socket对象.

Java网络编程之TCP程序设计

在Java中使用Socket(套接字)来完成TCP程序的开发,使用此类可以方便的建立可靠的.双向的.持续的.点对点的通信连接.服务器端使用ServerSocket等待客户端的连接,,而每一个客户端都是用一个Socket对象表示. 1.ServerSocket类与Socket类 ServerSocket类主要运用在服务器端开发,用于接收客户端的连接请求.常用方法: 类型 方法 描述 构造方法 ServerSocket(int port) 创建绑定到特定端口的服务器套接字. Socket accep

Java网络编程之TCP网络编程

一.基于Socket的TCP编程 Java语言的基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示: 二.客户端Socket的工作过程(四个基本步骤) 1.创建Socket根据指定服务端的IP地址或端口号构造Socket类对象.若服务器端响应,则建立客户端到服务器的通信线路:若连接失败,会出现异常.2.打开连接到Socket的输入出流使用getlnputStream()方法获得输入流,使用getOutputStream()方法获得输出流,进行数据传输.3.按照一定的协议对Socket

Java网络编程之tcp的socket通信

1.客户端MyClient.java 1 import java.io.*; 2 import java.net.*; 3 4 public class MyClient 5 { 6 public static void main(String[] args)throws Exception 7 { 8 Socket s = new Socket("192.168.1.1" , 30000); 9 // 客户端启动ClientThread线程不断读取来自服务器的数据 10 new Th

4.Java网络编程之TCP/UDP

常见传输协议: UDP , TCP UDP协议:    特点:         1.将数据及源和目的封装成数据包中,不需要建立连接         2.每个数据包的大小限制在64K内         3.因无连接,是不可靠协议         4.不需要建立连接,速度快 举例:比如你向家里邮寄一个包裹,无论家里此时是否有人,都会发送.当快递员发送到你家时,如果有人,家里人就收到了包裹,如果家里此时没有人,包裹(数据包)就被丢弃了. 自我理解: 当我们建立连接后,你说了一句:"你吃过饭了么?&qu

黑马程序员——Java网络编程之UDP传输

网络编程 网络模型 通讯要素:InetAddress(对象):ip地址,网络中设备的标识,不可记忆,可用主机名,本地回环地址:127.0.0.1主机名localhost 端口号 传输协议:UDP,将数据的源及目的封装成数据包中,不需要建立连接,每个数据包的大小限制在64K内,无连接,是不可靠协议,不需要建立连接,速度快.力求速度,不求数据的准确性.比如聊天软件,网络会议. TCP:建立连接,形成传输数据的通道,在连接中进行大数据量传输,通过三次握手完成连接,是可靠协议,必须建立连接效率稍低. S