互联网上那么多设备,java 是如何与其他设备通信的呢?这次的内容是网络通信的基础,有了它咱们才能上网页、玩游戏、视频聊天。

Socket 客户端套接字

Socket 客户端套接字,用于连接互联网提供服务的设备。

Socket 构造方法

构造方法 说明
Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号

常用方法

方法名称 说明
getOutputStream() 返回此套接字的输出流
getInputStream() 返回此套接字的输入流

下面示例模拟了一个 HTTP 请求

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner; public class TestSocket { public static void main(String[] args) { //创建套接字
try(Socket s=new Socket("www.baidu.com", 80);){
//创建向服务器发送数据的输出流
OutputStream os=s.getOutputStream();
StringBuffer sb=new StringBuffer();
//HTTP协议 请求报文
sb.append("GET / HTTP/1.1\r\n");
sb.append("Host: www.baidu.com:80\r\n");
sb.append("Connection: Keep-Alive\r\n");
//这里一定要一个回车换行,表示消息头完,不然服务器会等待
sb.append("\r\n");
//发送
os.write(sb.toString().getBytes());
//获取服务器相应内容
InputStream is=s.getInputStream();
//通过输入流创建扫描器,并指定编码为utf-8防止中文乱码
Scanner scanner=new Scanner(is,"utf-8"); while(scanner.hasNextLine()) {
String line=scanner.nextLine();
System.out.println(line);
}
} catch (UnknownHostException e) {
e.printStackTrace();
System.out.println("未知主机");
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常");
}
}
}

ServerSocket

ServerSocket:实现服务器套接字,服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner; public class TestServerSocket { public static void main(String[] args) {
//创建 ServerSocket 监听1666端口
try(ServerSocket server=new ServerSocket(1666)){
//阻塞方法,当有客户端连入,获取客户端Socket
try(Socket client=server.accept()){
//获取客户端发送的数据
InputStream is=client.getInputStream();
//获取向客户端发送数据的流
OutputStream os=client.getOutputStream();
//通过输入流创建扫描器
try(Scanner scanner=new Scanner(is)){ PrintWriter pw=new PrintWriter(os,true/*自动刷新*/);
//向客户端发送消息
pw.println("Hello,enter bye to exit.");
boolean done=false;
//客户端有输入数据并且没有发送 bye
while(!done&&scanner.hasNextLine()) {
//接收客户端发送的数据
String line=scanner.nextLine();
//将客户端发送的数据发回客户端
pw.println("Echo:"+line);
//如果客户端输入bye 结束通信
if(line.trim().equalsIgnoreCase("bye")) {done=true;}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

测试方式:

在DOS 中输入命令:telnet 127.0.0.1 1666

telnet 不是内部或外部命令的读者,需要在 Windows 功能中启用 Telnet 客户端。

上面的代码如果有多个客户端连入就不行了,如果希望服务能被多个客户端连接,可以使用线程。

多线程服务器

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner; public class TestMultiServerSocket { public static void main(String[] args) {
//创建 ServerSocket 监听 1666端口
try(ServerSocket server=new ServerSocket(1666)){
while(true) {
//accept() 是一个阻塞方法
Socket client=server.accept();
InputStream is=client.getInputStream();
OutputStream os=client.getOutputStream();
//开启新的线程处理,传入当前客户端
Thread t=new Thread(new ThreadEchoHandler(client));
t.start();
} } catch (IOException e) {
e.printStackTrace();
}
}
}
class ThreadEchoHandler implements Runnable{
private Socket socket=null; public ThreadEchoHandler(Socket socket) {
this.socket=socket;
}
@Override
public void run() {
try {
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
try(Scanner scanner=new Scanner(is)){
PrintWriter pw=new PrintWriter(os,true);
pw.println("Hello,enter bye to exit.");
boolean done=false;
while(!done&&scanner.hasNextLine()) {
String line=scanner.nextLine();
pw.println("Echo:"+line);
if(line.trim().equalsIgnoreCase("bye")) {done=true;}
}
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
} } }

URLConnection

抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。

Socket 可以默认任意类型的网络通信,URLConnection 更适合 HTTP 请求,使用 URLConnection 进行HTTP操作更方便,模拟请求报文,获取响应报文和内容。

URLConnection 常用方法

方法 说明
connect() 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)
getContentEncoding() 返回 content-encoding 头字段的值
getContentType() 返回 content-type 头字段的值
getHeaderFields() 返回头字段的不可修改的 Map
getInputStream() 返回从此打开的连接读取的输入流
setRequestProperty(String key, String value) 设置一般请求属性

获取 URLConnection 需要先创建 URL 对象:

URL url=new URL(host);

使用 URLConnection 获取网页的内容

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner; public class TestURLConnection {
public static void main(String[] args) { try {
//创建URL对象
URL url=new URL("http://www.baidu.com");
//创建 URLConnection对象
URLConnection connection=url.openConnection();
//设置请求属性
//connection.setRequestProperty("", "");
//连接
connection.connect();
//获取输入流
InputStream is=connection.getInputStream();
//通过输入流构建一个扫描器
Scanner scanner=new Scanner(is,"utf-8");
while(scanner.hasNextLine()) {
String line=scanner.nextLine();
System.out.println(line);
}
System.out.println("===响应头===");
Map<String,List<String>> headers=connection.getHeaderFields();
for (Entry<String, List<String>> entry: headers.entrySet()) {
String key=entry.getKey();
System.out.print(key+":");
for (String string : entry.getValue()) {
System.out.print(string);
}
System.out.println();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Java入门系列-24-实现网络通信的更多相关文章

  1. java io系列24之 BufferedWriter(字符缓冲输出流)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_24.html 更多内容请参考:java io系列01之 "目录" Buffere ...

  2. Java入门系列-26-JDBC

    认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...

  3. Java入门系列-19-泛型集合

    集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...

  4. Java入门系列-25-NIO(实现非阻塞网络通信)

    还记得之前介绍NIO时对比传统IO的一大特点吗?就是NIO是非阻塞式的,这篇文章带大家来看一下非阻塞的网络操作. 补充:以数组的形式使用缓冲区 package testnio; import java ...

  5. Java入门系列:实例讲解ArrayList用法

    本文通过实例讲解Java中如何使用ArrayList类. Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征.可以随时从链表中添 ...

  6. Java入门系列之hashCode和equals(十二)

    前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...

  7. Java入门系列之包装类(四)

    前言 上一节我们讲解了StringBuilder VS StringBuffer以及二者区别,本节我们来讲解包装类. 包装类 我们知道在Java中有8中基本数据类型,分为数值类型:byte.short ...

  8. Java入门系列之字符串创建方式、判断相等(一)

    前言 陆续从0开始学习Java出于多掌握一门语言以后的路也会更宽,.NET和Java兼顾,虽然路还很艰难,但事在人为.由于Java和C#语法相似,所以关于一些很基础的内容不会再重头讲,Java系列中所 ...

  9. Java入门系列之重写

    前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...

随机推荐

  1. C#图片缩放平移 —— 从功能分析到编码实现

    序 一直都是在看别人的博客,查到想要的,看完后把页面一关就万事大吉了,没啥感觉:直到后来遇到了同样的问题,总想不起来咋弄,关键是还查不到以前看过的,郁闷!现在想想,还是“好记性不如烂笔头”啊,自己弄过 ...

  2. html5 表格标签 table tr td

      最重要的三个 <table>     表格声明标签 属性: boarder    边框粗细 style    可配合css 使用 <tr>    行标签 table row ...

  3. WPF WebBrowser+TabControl MVVM模式 简单应用 提供源码下载

    源代码下载 这个程序是TabControl和Webbrowser的练手小程序 可达到练手目的有: MVVM设计模式的基本使用 Binding(包括相对源[RelativeSource]绑定)的基本使用 ...

  4. Red Hat安全性指南

    https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/security_guide/sec-usi ...

  5. [ActionScript 3.0] 利用ColorTransform实现对象(图片)的曝光过渡效果

    原图效果 过渡效果 这个效果可以用帧动画实现较为简单,只需要调节这个影片剪辑的色彩效果样式里面的高级选项的三个通道值,以下用代码简单测试,可作为文档类: package { import com.tw ...

  6. codis__通用的使用模式

    1,按功能模块分成不同的productName 参照 sample_user, sample_dynamic (见附件) sample_user.tar.gz,sample_dynamic.tar.g ...

  7. H5新手教程,小白来看看。

    H5教程(一) 相信点进来看这篇文章的应该都是刚刚接触H5的新手,那么你真的是找到了一篇合适的文章. 1.学习前准备 既然想学习好H5,只是这样看是不够的,还需要动手练习,以及及时复习,所以我推荐几款 ...

  8. mysql 快照读MVCC

    mysql的读分快照读和当前读 快照读 是指写的同时,读不阻塞,达到并发的作用 这时候的读 是 记录的历史版本,存在于undo里,当然回滚时就的也是这个undo 当执行一条update语句时,记录本身 ...

  9. nginx高性能WEB服务器系列之三版本升级

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  10. To 高一

    Linux 坑待填 Special Judge 什么是 Special Judge?有的题目会让你输出任意一个解即可AC,或者是让你输出部分答案能取得本测试点部分得分,或者是按照方案的优秀程度给你分, ...