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编程.
随机推荐
- Windows Server 2008 + IIS 7+ ASP.NET 并发优化
Windows Server 2008 + IIS 7+ ASP.NET 并发优化 站点出现这样的错误信息: Error Summary: HTTP Error 503.2 - Service Una ...
- 破解magento加密的密码算法
magento遇到丢掉密码的情况,其实很常见……比如我这记性,还好我比较暴力:-P 先看一段代码: /** * Hash a string * * @param s ...
- NodeJS包管理器之Yarn
一.安装yarn 首选必须先安装好NodeJS,之后可以去yarn官网下载mis安装程序安装.由于NodeJS自带了一个包管理器npm,所以安装yarn更简单的方法是直接使用npm install - ...
- css 设置div半透明 悬浮在页面底部 不随滚动条滚动
.action-button { width: 100%; background:rgba(0,0,0,0.7); position:fixed; bottom:; left:; z-index:; ...
- Node.js 动态网页爬取 PhantomJS 使用入门(转)
Node.js 动态网页爬取 PhantomJS 使用入门 原创NeverSettle101 发布于2017-03-24 09:34:45 阅读数 8309 收藏 展开 版权声明:本文为 winte ...
- 大话图解golang map
前言 网上分析golang中map的源码的博客已经非常多了,随便一搜就有,而且也非常详细,所以如果我再来写就有点画蛇添足了(而且我也写不好,手动滑稽).但是我还是要写,略略略,这篇博客的意义在于能从几 ...
- java html实体转义
public static void main(String[] args) { String str = " -<->-&-"-'" ...
- .NET ftp文件上传和下载
文章参考来源地址:https://blog.csdn.net/wybshyy/article/details/52095542 本次对代码进行了一点扩展:将文件上传到ftp指定目录下,若目录不存在则创 ...
- mybatis plus 支持达梦DM 数据库啦
最近由于公司项目需要使用DM数据库,现在就官方源码修改了,完美支持达梦数据库的代码生成器.官方说的v3.0.RELEASE版本支持达梦数据库,不知道说的支持包括支持代码生成器么? 怀着兴奋的心情,兴高 ...
- Win10 专业版 Hyper-V 主机计算服务无法启动
Windows 10升级1809版本后,发现Hyper-V不能用了,管理器里是一片空白,看服务Hyper-V 主机计算服务没有启动,手动启动的话失败,报错,代码1053. 自己尝试修复,也百度了很久, ...