Java知识回顾 (14)网络编程
本资料来自于runoob,略有修改。
网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。
java.net 包中 J2SE 的 API 包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。
Socket 编程
套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。
当连接建立时,服务器会创建一个 Socket 对象。客户端和服务器现在可以通过对 Socket 对象的写入和读取来进行通信。
java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。
以下步骤在两台计算机之间使用套接字建立TCP连接时会出现:
服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。
服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。
Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。
在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。
连接建立后,通过使用 I/O 流在进行通信,每一个socket都有一个输出流和一个输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
TCP 是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.以下是一些类提供的一套完整的有用的方法来实现 socket。
DEMO
客户端
// 文件名 GreetingClient.java import java.net.*;
import java.io.*; public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("连接到主机:" + serverName + " ,端口号:" + port);
Socket client = new Socket(serverName, port);
System.out.println("远程主机地址:" + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("服务器响应: " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
服务端
// 文件名 GreetingServer.java import java.net.*;
import java.io.*; public class GreetingServer extends Thread
{
private ServerSocket serverSocket; public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
} public void run()
{
while(true)
{
try
{
System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.run();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
阻塞和非阻塞网络编程
BIO(Blocking IO): 同步阻塞的编程方式
BIO编程方式通常是在JDK1.4版本之前常用的编程方式。编程实现过程为:首先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下ServerSocket回建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或遭到拒绝。
NIO (Unblocking IO): 同步非阻塞的编程方式
NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题,NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。也就是说,这个时候,已经不是一个连接就要对应一个处理线程了,而是有效的请求,对应一个线程,当连接没有数据时,是没有工作线程来处理的。
AIO(Asynchronous IO): 异步非阻塞的编程方式
与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。在JDK1.7中,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:AsynchronousSocketChannel、AsynchronousServerSocketChannel、AsynchronousFileChannel、AsynchronousDatagramChannel
bio示例
public class Server {
public static void main(String[] args) {
int port = genPort(args);
ServerSocket server = null;
ExecutorService service = Executors.newFixedThreadPool(50);
try{
server = new ServerSocket(port);
System.out.println("server started!");
while(true){
Socket socket = server.accept();
service.execute(new Handler(socket));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(server != null){
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
server = null;
}
}
static class Handler implements Runnable{
Socket socket = null;
public Handler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader reader = null;
PrintWriter writer = null;
try{
reader = new BufferedReader(
new InputStreamReader(socket.getInputStream(), "UTF-8"));
writer = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
String readMessage = null;
while(true){
System.out.println("server reading... ");
if((readMessage = reader.readLine()) == null){
break;
}
System.out.println(readMessage);
writer.println("server recive : " + readMessage);
writer.flush();
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
reader = null;
if(writer != null){
writer.close();
}
writer = null;
}
}
}
private static int genPort(String[] args){
if(args.length > 0){
try{
return Integer.parseInt(args[0]);
}catch(NumberFormatException e){
return 9999;
}
}else{
return 9999;
}
}
}
server
client
public class Client {
public static void main(String[] args) {
String host = null;
int port = 0;
if(args.length > 2){
host = args[0];
port = Integer.parseInt(args[1]);
}else{
host = "127.0.0.1";
port = 9999;
}
Socket socket = null;
BufferedReader reader = null;
PrintWriter writer = null;
Scanner s = new Scanner(System.in);
try{
socket = new Socket(host, port);
String message = null;
reader = new BufferedReader(
new InputStreamReader(socket.getInputStream(), "UTF-8"));
writer = new PrintWriter(
socket.getOutputStream(), true);
while(true){
message = s.nextLine();
if(message.equals("exit")){
break;
}
writer.println(message);
writer.flush();
System.out.println(reader.readLine());
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
reader = null;
if(writer != null){
writer.close();
}
writer = null;
}
}
}
UDP简单示例
服务端
public class Server {
public static void main(String[] args) {
try {
DatagramSocket server = new DatagramSocket(5060);
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
server.receive(packet);
System.out.println(packet.getAddress().getHostName() + "(" + packet.getPort() + "):" + new String(packet.getData()));
packet.setData("Hello Client".getBytes());
packet.setPort(5070);
packet.setAddress(InetAddress.getLocalHost());
server.send(packet);
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
public class Client {
public static void main(String[] args){
try {
DatagramSocket client = new DatagramSocket(5070);
DatagramPacket packet = new DatagramPacket(new byte[1024],1024);
packet.setPort(5060);
packet.setAddress(InetAddress.getLocalHost());
packet.setData("Hello Server".getBytes());
client.send(packet);
client.receive(packet);
System.out.println(packet.getAddress().getHostName() + "(" + packet.getPort() + "):" + new String(packet.getData()));
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Java知识回顾 (14)网络编程的更多相关文章
- Java知识回顾 (1) 编译环境与基本变量类型
参考资料 runoob Java知识回顾序列的相关资料,主要来自 runoob,并对其中的知识进行概况或总结,去除对一个之前了解过Java的人员无关的知识点.以便能够使得一个新手,或之前有Java经验 ...
- 20165310 Java实验五《网络编程与安全》
20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java知识回顾 (11) 异常处理
距离最近的 Java知识回顾系列(10),2019.4.24日,到现在,已经近半年过去了. 感觉,做一件事情,如果有头无尾,实在不好,心里会一直悬着.所以,现在继续上面的内容. 再次声明,正如(1)中 ...
- java架构《Socket网络编程基础篇》
本章主要介绍Socket的基本概念,传统的同步阻塞式I/O编程,伪异步IO实现,学习NIO的同步非阻塞编程和NIO2.0(AIO)异步非阻塞编程. 目前为止,Java共支持3种网络编程模型:BIO.N ...
- 【Java】简单了解网络编程
文章目录 网络编程 网络编程中有两个主要的问题 网络编程中的两个要素 通信要素一:IP和端口号 实例化InetAddress 两个常用方法 端口号 通信要素二:网络通信协议 实现TCP的网络编程 例子 ...
- Java 基础高级2 网络编程
1.协议的概念:通信双方事先约定好的通信规则 2七层网络通信协议:应用成,表示层,会话层,传输层,网络层,数据链路层 3.TCP/IP协议:点对点通信,三层握手,安全有保证 4.UDP协议;广播协议, ...
- java 基础之--nio 网络编程
在传统的Java 网络编程中,对于客户端的每次连接,对于服务器来说,都要创建一个新的线程与客户端进行通讯,这种频繁的线程的创建,对于服务器来说,是一种巨大的损耗,在Java 1.4 引入Java ni ...
- java基础学习总结——网络编程
一.网络基础概念 首先理清一个概念:网络编程 != 网站编程,网络编程现在一般称为TCP/IP编程.
随机推荐
- 自动创建Kibana索引
参考 https://www.cnblogs.com/dance-walter/p/10471950.html 参考 https://www.elastic.co/guide/en/kibana/cu ...
- maven本地仓库已经有了所需的jar包,为什么还要去请求远程仓库
问题 IDEA 中的maven 项目,一个jar包一直导入不进来,reimport 无效.从另一仓库把这个jar包拷贝到当前仓库,还是无效.mvn clean install -e U 发现加载这个j ...
- java--poi读取excel图片和内容(支持03版本)
有的时候需要将excel中所包含的图片在导入的时候取出来存到服务器中, 详细实现代码如下: package com.liuf.util; import java.io.BufferedInputStr ...
- 从ASP.NET到ASP.NET Core差异变化
MSDN原文:链接 ASP.NET Core项目为开发人员提供了针对.NET Core,.NET Framework2种实现方式,根据官网通告NETCORE3.0后将取消对.NET Framework ...
- 使用 Visual Studio Code(VSCode)搭建简单的Python+Django开发环境的方法步骤
安装配置 VSCode [1]安装 VSCode: 下载地址:https://code.visualstudio.com/ 根据自己电脑对应的操作系统下载对应的版本即可,至于安装过程也和一般的软件一样 ...
- windows下安装zk
1 下载安装包并解压 2 修改conf下配置文件名字 zoo_sample.cfg 文件名改为 zoo.cfg 3 启动zk zKServer.cmd 4启动客户端连接测试 zKCli.cmd 127 ...
- Cisco ASA 5505配置详解(v8.3之前版本)
在配ASA 5505时用到的命令 2009-11-22 22:49 nat-control命令 在6.3的时候只要是穿越防火墙都需要创建转换项,比如:nat:static等等,没有转换项是不能穿越防火 ...
- 使用Python解压zip、rar文件
解压 zip 文件 基本解压操作 import zipfile ''' 基本格式:zipfile.ZipFile(filename[,mode[,compression[,allowZip64]]]) ...
- linux下 tab键失效 -bash: !ref: 为绑定变量
报错现象: Linux环境下,按Tab键进行补全时出现上图情况. [root@worker2 cjj]# vim /et-bash: !ref: 为绑定变量 -bash: !ref: 为绑定变量 -b ...
- [Linux.centOS].安装Redis 腾讯云
环境 { "服务器运营商":"腾讯云", "操作系统":"CentOS 7.5 64位", "CPU" ...