[学习笔记]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();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值