Java Socket
来源:互联网 发布:尔雅网络通识课官网 编辑:程序博客网 时间:2024/06/17 17:49
本文内容来自Java Socket应用—通信是这样练成的,记录下学习的内容
Java Socket
TCP/IP协议是目前应用最为广泛的协议,TCP传输控制协议,IP互联网协议。
应用层协议:
- HTTP
- FTP
- SMTP简单邮件传送协议
- Telnet远程登录服务
IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。
InetAddress
InetAddress类标识网络上的硬件资源,标识互联网协议(IP)地址。
获取InetAddress
的实例
1.通过类方法获取
InetAddress address = InetAddress.getLocalHost();
2.根据机器名获取InetAddress
实例
InetAddress address2 = InetAddress.getByName("WinfredZen");
3.根据IP地址来获取InetAddress
实例
InetAddress address3 = InetAddress.getByName("192.168.0.1");
一些常用方法
getHostName()
获取计算机名 getHostAddress()
获取IP地址获取字节形式的IP地址
byte[] bytes = address.getAddress();System.out.println("字节数组形式的IP:"+Arrays.toString(bytes));
URL
URL
统一资源定位符,表示Internet上某一资源的地址。 URL
由两部分组成:协议名称和资源名称,中间由冒号隔开。
在java.net
包中,提供了URL
类来表示URL
构造方法
URL imooc = new URL("http://www.baidu.com");URL url = new URL(imooc, "index.html?username=tom#test")
常用方法
示例说明使用上面创建的的url
getProtocol()
获取协议 http
getHost()
获取主机 www.baidu.com
getPort()
获取端口 -1
java.net.URL.getPort()
规定,若URL的实例未申明(省略)端口号,则返回值为-1
getPath()
获取文件路径 /index.html
getFile()
获取文件名 /index.html?username=tom
getRef()
获取相对路径 test
getQuery()
获取查询字符串 username=tom
使用URL读取网页内容
1.通过URL
对象的openStream()
方法可以得到指定资源的输入了
2.通过输入流可以读取、访问网络上的数据
如下:
try { URL url = new URL("http://www.baidu.com"); //获取URL对象所表示的资源的字节输入流 InputStream in = url.openStream(); //将字节输入流转换为字符输入流 InputStreamReader isr = new InputStreamReader(in, "utf-8"); //为字符输入流添加缓冲 BufferedReader br = new BufferedReader(isr); //读取数据 String data = br.readLine(); while (data != null) { System.out.println(data); data = br.readLine(); } br.close(); isr.close(); in.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}
TCP
TCP
协议是面向连接、可靠的、有序的,以字节流的方式发送数据。
Java中基于TCP协议实现网络通信的类
1.客户端的Socket
类
2.服务端的ServerSocket
类
Socket通信模型
Socket通信实现步骤
1.创建ServerSocket
和Socket
2.打开连接到Socket
的输入/输出流
3.按照协议对Socket
进行读/写操作
4.关闭输入输出流、关闭Socket
编程实现基于 TCP 的 Socket 通信
服务器端
1.创建ServerSocket
对象,绑定监听端口
2.通过accept()
方法监听客户端请求
3.连接建立后,通过输入流读取客户端发送的请求消息
4.通过输出流向客户端发送响应信息
5.关闭相关资源
package com.imooc;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;/* * 服务端 */public class Server { public static void main(String[] args) { try { //创建服务端的socket ServerSocket serverSocket = new ServerSocket(8882); //调用accept()方法开始监听 System.out.println("***服务器即将启动,等待客户端的连接***"); Socket socket = serverSocket.accept(); //获取输入流,读取客户端发送的登录信息 InputStream is = socket.getInputStream();//字节输入流 InputStreamReader isr = new InputStreamReader(is);//将字节流转为字符流 BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲 String info = null; while ((info=br.readLine()) != null) { System.out.println("***我是服务器,客户端说:"+ info+"***"); } //关闭输入流 socket.shutdownInput(); //获取输出流,响应客户端的请求 OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); pw.write("欢迎您!"); pw.flush(); //关闭资源 pw.close(); os.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); System.out.println("服务端关闭连接"); } catch (IOException e) { e.printStackTrace(); } }}
客户端
1.创建Socket对象,指明需要连接的服务器的地址和端口号
2.连接建立后,通过输出流向服务器端发送请求消息
3.通过输入流获取服务器响应的消息
4.关闭相关资源
package com.imooc;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;public class Client { public static void main(String[] args) { try { //创建socket,指定服务器地址和端口 Socket socket = new Socket("localhost", 8882); //获取输出流,向服务器端发送登录信息 OutputStream os = socket.getOutputStream();//字节输出流 PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流 pw.write("用户名:admin;密码:123"); pw.flush(); //关闭输出流 socket.shutdownOutput(); //获取输入流 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String info = null; while ((info=br.readLine()) != null) { System.out.println("***我是客户端,服务端说:"+ info+"***"); } //关闭资源 br.close(); is.close(); pw.close(); os.close(); socket.close(); System.out.println("客户端关闭"); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
使用多线程实现多客户端的通信
应用多线程来实现服务器与多客户端之间的通信。
基本步骤:
1.服务端创建ServerSocket
,循环调用accept()
等待客户端连接
2.客户端创建一个socket
并请求和服务端连接
3.服务端接受客户端请求,创建socket
与该客户建立专线连接
4.建立连接的两个socket
在一个单独的线程上对话
创建ServerThread
类继承自Thread
package com.imooc;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;/* * 服务器线程处理类 */public class ServerThread extends Thread { private Socket socket = null; public ServerThread(Socket socket) { this.socket = socket; } @Override public void run() { InputStream is = null; InputStreamReader isr = null; BufferedReader br = null; OutputStream os = null; PrintWriter pw = null; try { //获取输入流,读取客户端发送的登录信息 is = socket.getInputStream();//字节输入流 isr = new InputStreamReader(is);//将字节流转为字符流 br = new BufferedReader(isr);//为输入流添加缓冲 String info = null; while ((info=br.readLine()) != null) { System.out.println("***我是服务器,客户端说:"+ info+"***"); } //关闭输入流 socket.shutdownInput(); //获取输出流,响应客户端的请求 os = socket.getOutputStream(); pw = new PrintWriter(os); pw.write("欢迎您!"); pw.flush(); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 try { if (pw != null) { pw.close(); } if (os != null) { os.close(); } if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (is != null) { is.close(); } if (socket != null) { } } catch (IOException e) { e.printStackTrace(); } } }}
服务器端代码:
package com.imooc;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;/* * 服务端 */public class MutiServer { public static void main(String[] args) { try { //创建服务端的socket ServerSocket serverSocket = new ServerSocket(8882); System.out.println("***服务器即将启动,等待客户端的连接***"); Socket socket = null; //记录连接数量 int count = 0; //循环监听等待客户端的连接 while (true) { //调用accept()方法开始监听 socket = serverSocket.accept(); //创建一个新的线程 ServerThread serverThread = new ServerThread(socket); //启动线程 serverThread.start(); count++; System.out.println("连接数量:"+count); InetAddress address = socket.getInetAddress(); System.out.println("客户单当前IP地址:"+address.getHostAddress()); } } catch (IOException e) { e.printStackTrace(); } }}
调试,控制台可能有如下的输出:
客户单当前IP地址:127.0.0.1***我是服务器,客户端说:用户名:admin;密码:123***连接数量:2客户单当前IP地址:127.0.0.1***我是服务器,客户端说:用户名:admin;密码:123***
编程实现基于 UDP 的 Socket 通信
UDP协议(用户数据报协议)是无连接、不可靠的、无序的
UDP协议以数据报作为数据传输的载体。
进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据所要到达的Socket(主机地址和端口号),然后再将数据报发送出去。
相关的操作类
DatagramPacket
表示数据包DatagramSocket
进行端到端通信的类
服务端
1.创建DatagramSocket
,指定端口号
2.创建DatagramPacket
,用来接收客户端发送的数据
3.接收客户端发送的数据信息
4.读取数据
package com.imooc;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;/* * 服务端,实现基于UDP的用户登录 */public class UDPServer { public static void main(String[] args) throws IOException { /* * 接收客户端发送的数据 */ //创建服务端DatagramSocket,指定端口 DatagramSocket socket = new DatagramSocket(8889); //创建数据报,用于接收客户端发送的数据 byte[] data = new byte[1024];//创建字节数组,指定接收的数据包的大小 DatagramPacket packet = new DatagramPacket(data, data.length); //接收客户端发送的数据 socket.receive(packet);//此方法在接收到数据之前,会一直阻塞 //读取数据 String info = new String(data, 0, packet.getLength()); System.out.println("我是服务器,客户端说:" + info); /* * 向客户端响应数据 */ //定义客户端的地址,端口号、数据 InetAddress address = packet.getAddress(); int port = packet.getPort(); byte[] dataToSend = "欢迎您".getBytes(); //创建数据报,包含响应的数据信息 DatagramPacket packet2 = new DatagramPacket(dataToSend, dataToSend.length,address, port); //响应客户端 socket.send(packet2); //关闭资源 socket.close(); }}
客户端
1.定义发送信息
2.创建DatagramPacket
,包含我们要发送的信息
3.创建DatagramSocket
,用来实现数据的发送
4.发送数据
package com.imooc;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/* * 客户端实现 */public class UDPClient { public static void main(String[] args) throws IOException { /* * 向服务器发送数据 */ //定义服务器的地址、端口号 InetAddress address = InetAddress.getByName("localhost"); int port = 8889; byte[] data = "用户名:admin;密码:123".getBytes(); //创建数据报,包含发送的数据 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); //创建DatagramSocket对象 DatagramSocket socket = new DatagramSocket(); //向服务器发送数据报 socket.send(packet); /* * 接收服务器响应数据 */ //创建数据报,用于接收数据端响应的数据 byte[] data2 = new byte[1024]; DatagramPacket packet2 = new DatagramPacket(data2, data2.length); //接收服务器响应的数据 socket.receive(packet2); //读取数据 String reply = new String(data2,0, packet2.getLength()); System.out.println("我是客户端,服务器说:"+reply); //关闭资源 socket.close(); }}
总结
1.多线程的优先级
未设置优先级可能会导致运行时速度非常慢,可降低优先级
2.是否关闭输出流和输入流
对应同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可
3.使用TCP通信传输对象
4.socket编程传递文件
Java Socket应用
- java socket (-) 简单socket
- Java Socket
- java-socket
- java socket
- Java Socket
- JAVA Socket
- Java Socket
- socket(java)
- Java Socket
- Java socket
- java socket
- java socket
- Socket(java)
- Java socket
- Java Socket
- java socket
- Java Socket
- java socket
- powershell 批量添加TMG ISA 域名集
- C#将数据存储为CSV文件格式
- mysql函数和mysqli函数用法详解
- android.media.cts.EncodeDecodeTest -- testVP8EncodeDecodeVideoFromPersistentSurfaceToSurfaceQCIF
- 关于“我”
- Java Socket
- DAG模型的动态规划学习
- STM32-内部结构
- AngularJS select
- 【OpenCV】opencv处理透明图片
- 区块链开发(二)以太坊客户端基本操作命令
- 【OTT】1月2日-1月8日OTT盒子观察报告
- 关于Apache/Tomcat/JBOSS/Neginx/lighttpd/Jetty等一些常见服务器的区别比较和理解
- 小伙的java之旅——容器