Java入门系列-24-实现网络通信
互联网上那么多设备,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-实现网络通信的更多相关文章
- java io系列24之 BufferedWriter(字符缓冲输出流)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_24.html 更多内容请参考:java io系列01之 "目录" Buffere ...
- Java入门系列-26-JDBC
认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...
- Java入门系列-19-泛型集合
集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...
- Java入门系列-25-NIO(实现非阻塞网络通信)
还记得之前介绍NIO时对比传统IO的一大特点吗?就是NIO是非阻塞式的,这篇文章带大家来看一下非阻塞的网络操作. 补充:以数组的形式使用缓冲区 package testnio; import java ...
- Java入门系列:实例讲解ArrayList用法
本文通过实例讲解Java中如何使用ArrayList类. Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征.可以随时从链表中添 ...
- Java入门系列之hashCode和equals(十二)
前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...
- Java入门系列之包装类(四)
前言 上一节我们讲解了StringBuilder VS StringBuffer以及二者区别,本节我们来讲解包装类. 包装类 我们知道在Java中有8中基本数据类型,分为数值类型:byte.short ...
- Java入门系列之字符串创建方式、判断相等(一)
前言 陆续从0开始学习Java出于多掌握一门语言以后的路也会更宽,.NET和Java兼顾,虽然路还很艰难,但事在人为.由于Java和C#语法相似,所以关于一些很基础的内容不会再重头讲,Java系列中所 ...
- Java入门系列之重写
前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...
随机推荐
- TSQL--NESTED LOOPS JOIN
算法:遍历外表,将遍历出结果依次在内标中匹配查找 --如果内表无索引,则扫描内表 foreach(row r1 in outerTable) { foreach(row r2 in innerTabl ...
- 关于C#/sqlserver生成32位数据库字段总结
一.C#中用Guid.NewGuid().ToString() Sql中用NEWID() 以上方法生成的是36位的GUID,如果需要转换成32位,则需要替换掉其中的'-'字符. Sql中的方法:r ...
- 快速搭建windows服务器的可视化运维环境
开发好的程序部署在服务器上,如何对服务器的基本指标进行监控呢?最近对一套工具进行了研究,可以快速搭建服务器监管环境,很是强大,最重要的是它还很酷炫. 原理:数据采集+时序数据库+可视化,下面记录一下搭 ...
- c# 判断两个集合是否有交集
/// <summary> /// 判断是否有交集 /// </summary> /// <typeparam name="T"></ty ...
- C#生成二维码(加源码)
使用工具: Visual Studio(VS) 2013 第一步: 要用到一个类:QRCodeEncoder 这个类要添加一个动态库:ThoughtWorks.QRCode.dll(项目中有带) 然后 ...
- php-fpm.conf 解析
以下内容转自:http://www.4wei.cn/archives/1002061 约定几个目录/usr/local/php/sbin/php-fpm/usr/local/php/etc/php-f ...
- iOS开发之静态库.a 以及合并
静态库和动态库 静态库和动态库的存在形式静态库: .a 和 .framework 动态库: .dylib 和 .framework 静态库和动态库在使用上的区别静态库:链接时,静态库会被完整地复制到可 ...
- uC/OS-II 函数之消息队列相关函数
上文主要介绍了信号量相关的函数,本文介绍消息队列相关的函数:OSQCreate()建立消息队列函数,OSQPend()任务等待消息函数,其他的消息函数. 消息队列介绍 消息队列是µC/OS-II中另一 ...
- unity里的c#
类方法:start只进行一次,update每一帧都会进行调用 拖动脚步到对应物体就可以将其关联 定义变量与c++相似 F2修改文件名 脚本的类名要与文件名保持一致 数组的定义:1.类型[] 数组名={ ...
- iOS8 dismissViewControllerAnimated:YES在Show Segue不工作
最近使用iOS8 Sdk(xcode6.1.1)使用Show Segue功能,V_A视图push到V_B视图,然后想通过使用按键返回V_A,我记得ios6的时候可以使用[self dismissVie ...