Java中Socket网络通信
Posted java小龙菜鸟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中Socket网络通信相关的知识,希望对你有一定的参考价值。
目录
网络协议信息
- TCP
传输控制协议(Transmission Control Protocol)
- IP
互联网协议(Internet Protocol)
- HTTP
超文本传输协议(默认端口号为80)
- FTP
文件传输协议(默认端口号为:21)
- Telnet
(远程登录服务,默认端口号为:23)
InetAddress类的应用
用于标识网络上的硬件资源(表示标识ip地址),InetAddress的实例对象包含以数字形式保存的IP地址,同时还可能包含主机名(如果使用主机名来获取InetAddress的实例,或者使用数字来构造,并且启用了反向主机名解析的功能)。InetAddress类提供了将主机名解析为IP地址(或反之)的方法。
代码块
/*用于网络上的硬件资源,表示互联网协议(IP)地址**/
public static void main(String[] args) throws UnknownHostException {
//获取本机的InetAddress实列
InetAddress address = InetAddress.getLocalHost();
//获取本机名称
System.out.println("计算机名称:"+address.getHostName());
//获取本机IP
System.out.println("本机IP地址:"+address.getHostAddress());
//获取本机IP地址的字节数组形式
byte[] bytes=address.getAddress();
System.out.println("本机IP地址的字节数组形式:"+Arrays.toString(bytes));
//直接输出InetAddress对象
System.out.println(address);
System.out.println("------------------------------");
//根据主机名获取InetAddress实列
//InetAddress address2=InetAddress.getByName("XLP007");
//根据ip地址获取InetAddress实列
InetAddress address2=InetAddress.getByName("192.168.0.126");
//获取其他主机名称
System.out.println("计算机名称:"+address2.getHostName());
//获取其他主机IP地址
System.out.println("IP地址名称:"+address2.getHostAddress());
//IP地址的字节数组形式
//byte[] bytes2=address.getAddress();
//System.out.println("IP地址的字节数组形式:"+Arrays.toString(bytes2));
//直接输出InetAddress对象
//System.out.println(address2);
}
URL类的应用
1.Uniform Resource Locator 统一资源定位符,表示Internet上某一资源的地址;
2.URL由两部分组成:协议名称和资源名称,中间用冒号隔开;
3.在java.net包中,提供了URL类来表示URL,通过URL可以直接读取或写入网络上的数据;
代码块:通过URL获取信息
public static void main(String[] args) {
try {
//创建一个URL实例
URL bd = new URL("http://www.baidu.com");
//通过父节点获取URL实例(?后面的是参数,#后面的锚点)
URL url=new URL(bd,"/index.html?userName=lixiaolong#test");
//获取协议
System.out.println("协议: "+url.getProtocol());
//获取主机
System.out.println("主机: "+url.getHost());
//获取文件
System.out.println("文件: "+url.getFile());
//获取端口号(如果未指定端口号,则使用默认的端口号,但是getPort()方法返回的
//是-1,getDefaultPort()方法返回默认端口号)
System.out.println("端口号: "+url.getPort());
System.out.println("默认端口号: "+url.getDefaultPort());
//获取文件路径
System.out.println("文件路径: "+url.getPath());
//获取参数
System.out.println("参数: "+url.getQuery());
//获取锚点
System.out.println("锚点: "+url.getRef());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
基于TCP的Socket通信
简介:TCP协议是面向连接、可靠的、有序的,以字节流的方式发送数据
基于TCP协议实现网络通信的类
- 客户端的Socket类
- 服务端的ServerSocket类
Socket通信实现步骤
1.分别在服务端和客户端创建ServerSocket和Socket
2.打开连接到Socket的输入/输出流
3.按照协议对Socket进行读/写操作
4.关闭输入输出流,关闭Socket(千万不要忘记这一步)
代码块:基于Tcp协议的Socket通信,实现用户登录
server.java
public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
//(注意,要1023以后的端口,因为1023以前的端口已经用于通用的应用中了)
ServerSocket serverSocket=new ServerSocket(8989);
//2.调用accept()方法开始监听,等待客户端的连接
System.out.println("*****服务器即将启动,等待客户端的连接******");
//返回一个Socket对象给客户端
Socket socket = serverSocket.accept();
//3.获取输入流对象,并读取客户端信息
InputStream is = socket.getInputStream();//字节输入流
//将字节输入流转换为字符输入流
InputStreamReader isr=new InputStreamReader(is);
//将字符输入流放入缓冲中
BufferedReader br=new BufferedReader(isr);
//定义一个变量保存读取客户端的信息
String msg=null;
//5.循环读取客户端的信息
while((msg=br.readLine())!=null){
System.out.println("我是服务器,客户端的信息是:"+msg);
}
//关闭输入流对象
socket.shutdownInput();
//4.创建输出流,响应客服端的请求
OutputStream os=socket.getOutputStream();
//创建打印输出流,包装输出流
PrintWriter pw=new PrintWriter(os);
//输出一句话
pw.write("客户端,欢迎您!!");
//调用flush()方法刷新缓冲
pw.flush();
//关闭相关资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
client.java
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口号
Socket socket=new Socket("localhost",8989);
//获取输出流对象,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
//将字节输出流对象转换为打印输出流对象
PrintWriter pw=new PrintWriter(os);
pw.write("用户名:admin;密码:123456");
//调用flush来刷新缓冲
pw.flush();
//关闭输出流(一定要放在这里)
socket.shutdownOutput();
//创建输入流输出服务器端响应的信息
InputStream is=socket.getInputStream();
//将字节输入流对象转换为字符输入流对象
InputStreamReader isr=new InputStreamReader(is);
//创建BufferedReader来包装输入流
BufferedReader br=new BufferedReader(isr);
//定义一个变量保存响应的信息
String msg=null;
//循环读取服务器响应的信息
while((msg=br.readLine()) !=null){
System.out.println("我是客户端,服务器说: "+msg);
}
//关闭相关资源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
代码块:引用多线程应用实现多个用户访问服务器
serverThread.java(多线程)
//定义一个Socket对象
Socket socket=null;
//定义一个构造方法创建实例
public ServerThread(Socket socket){
this.socket=socket;
}
//定义线程执行操作,响应客户端的请求
public void run(){
//3.获取输入流对象,并读取客户端信息
InputStream is=null;
//将字节输入流转换为字符输入流
InputStreamReader isr=null;
//将字符输入流放入缓冲中
BufferedReader br=null;
//4.创建输出流,响应客服端的请求
OutputStream os=null;
//创建打印输出流,包装输出流
PrintWriter pw=null;
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
//定义一个变量保存读取客户端的信息
String msg=null;
//5.循环读取客户端的信息
while((msg=br.readLine())!=null){
System.out.println("我是服务器,客户端的信息是:"+msg);
}
//关闭输入流对象
socket.shutdownInput();
os = socket.getOutputStream();
pw = new PrintWriter(os);
//输出一句话
pw.write("客户端,欢迎您!!");
//调用flush()方法刷新缓冲
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
//因为相关资源一定要关闭,所以房租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)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
----------
ServerSocketThread.java(服务器端)
public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
//(注意,要1023以后的端口,因为1023以前的端口已经用于通用的应用中了)
ServerSocket serverSocket=new ServerSocket(8989);
Socket socket =null;
//定义一个变量保存客户端的数量
int count=0;
//2.调用accept()方法开始监听,等待客户端的连接
System.out.println("*****服务器即将启动,等待客户端的连接******");
//因为多线程,所以要循环监听和等待客户端的连接
while(true){
//调用accept()方法循环监听客户端,并响应客户端
socket=serverSocket.accept();
//创建一个新的线程
ServerThread serverThread=new ServerThread(socket);
//执行线程
serverThread.start();
//输出访问服务器客户端的ip地址
InetAddress address=socket.getInetAddress();
System.out.println("当前的IP地址为: "+address.getHostAddress());
//输出访问该服务器的客户端的数量
count++;
System.out.println("当前访问服务器的数量为: "+count);
}
//因为是多线程,所以socket不能关闭
//serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
----------
ClientSocketThread.java(客户端)
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口号
Socket socket=new Socket("localhost",8989);
//获取输出流对象,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
//将字节输出流对象转换为打印输出流对象
PrintWriter pw=new PrintWriter(os);
pw.write("用户名:张三;密码:123456");
//调用flush来刷新缓冲
pw.flush();
//关闭输出流(一定要放在这里)
socket.shutdownOutput();
//创建输入流输出服务器端响应的信息
InputStream is=socket.getInputStream();
//将字节输入流对象转换为字符输入流对象
InputStreamReader isr=new InputStreamReader(is);
//创建BufferedReader来包装输入流
BufferedReader br=new BufferedReader(isr);
//定义一个变量保存响应的信息
String msg=null;
//循环读取服务器响应的信息
while((msg=br.readLine()) !=null){
System.out.println("我是客户端2,服务器说: "+msg);
}
//关闭相关资源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
基于UDP的socket通信
1.简介
1.基本介绍:UDP协议(用户数据报协议)是无连接、不可靠的、无序的,速度相对比较快,以数据报为载体
2.UDP是如何传输的:进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据报 要达到的Socket(主机地址和端口号),然后再将数据报发送出去
2.相关通信类
DatagramPacket:数据报类
DatagramSocket:进行端到端通信的类
3.实现步骤
1.服务器端实现步骤
①创建DatagramSocket,指定相应的端口号
②创建DatagramPacket,用来接受客户端发送的数据
③接受客户端发送的数据信息
④读取数据
2.客户端实现步骤
①定义发送的信息(服务器的地址,端口号以及内容)
②创建DatagramPacket,包含要发送的信息
③创建DatagramSocket,用来实现数据的发送
④发送数据
代码块:实现基于UDP的用户登录通信
Server.java(服务器端)
public static void main(String[] args) throws IOException {
/**
* 接收客户端发送的数据
* */
//1.创建DatagramSocket对象,指定服务器的端口
DatagramSocket socket=new DatagramSocket(8989);
//2.创建DatagramPacket对象,指定接受客户端发送的信息
//首先创建一个字节保存信息
byte[] data=new byte[1024];
DatagramPacket packet=new DatagramPacket(data,data.length);
//3.接受客户端发送的信息
System.out.println("*****服务器已经启动,等待客户端发送数据****");
socket.receive(packet);//此方法在接收到数据之前会一直处在阻塞状态
//4.读取数据
String info=new String(data, 0, packet.getLength());
System.out.println("我是服务器,客户端说: "+info);
/**
* 响应客户端的请求
*
* */
//1.定义响应客户端的地址、端口号、数据
//通过数据报获取客户端的地址
InetAddress address=packet.getAddress();
//通过数据报获取客户端的端口号
int port=packet.getPort();
//定义发送的数据
byte[] data2="欢迎您!".getBytes();
//2.创建数据报,来保存要响应客户端的信息
DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);
//3.调用Socket
socket.send(packet2);
//4.千万不要忘记关闭相关资源
socket.close();
}
----------
client.java(客户端)
public static void main(String[] args) throws IOException {
/**
* 发送信息到服务器
* */
//1.定义发送的信息(服务器地址,端口号)
//定义服务器地址
InetAddress address=InetAddress.getByName("localhost");
//定义端口号
int port=8989;
//定义要发送的内容,要用字节来
byte[] data="用户名:张三;密码:123456".getBytes();
//2.创建DatagramPacket对象保存客户端要发送的数据
DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
//3.创建DatagramSocket发送数据
DatagramSocket socket=new DatagramSocket();
//4.发送数据
socket.send(packet);
/**
* 接收服务器响应的信息
* */
//1.创建DatagramPacket对象,接收服务器发送的信息
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2,0,data2.length);
//2.接收服务器发送的信息
socket.receive(packet2);
//3.读取服务器发送的信息
String info=new String(data2,0,packet.getLength());
System.out.println("我是客户端,服务器说: "+info);
//4.关闭资源(千万不要忘记了)
socket.close();
}
代码块:引用多线程实现多个用户访问服务器
ServerThread.java(多线程)
//定义一个DatagramSocket对象
private DatagramSocket socket;
private DatagramPacket packet;
//定义一个构造函数初始化对象
public ServerThread(DatagramSocket socket,DatagramPacket packet){
this.socket=socket;
this.packet=packet;
}
//定义一个线程执行方法
public void run(){
try {
/**
* 接收客户端发送的数据
* */
//1.读取数据
String info=new String(packet.getData(), 0, packet.getLength());
System.out.println("我是服务器,客户端说: "+info);
/**
* 响应客户端的请求
*
* */
//1.定义响应客户端的地址、端口号、数据
//通过数据报获取客户端的地址
InetAddress address=packet.getAddress();
System.out.println("当前客户端的IP地址为: "+address);
//通过数据报获取客户端的端口号
int port=packet.getPort();
//定义发送的数据
byte[] data2="欢迎您!".getBytes();
//2.创建数据报,来保存要响应客户端的信息
DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);
//3.调用Socket
socket.send(packet2);
} catch (IOException e) {
e.printStackTrace();
}
}
----------
UDPServerThread.java(服务器端)
public static void main(String[] args) throws IOException {
/**
* 接收客户端发送的数据
* */
//1.创建DatagramSocket对象,指定服务器的端口,初始化DatagramSocket对象
DatagramSocket socket=new DatagramSocket(8989);
//定义一个变量保存客户端的数量
int count=0;
System.out.println("*****服务器已经启动,等待客户端的连接****");
//因为多线程,所以要循环监听和等待客户端的连接
while(true){
byte[] data=new byte[1024];
//创建一个DatagramPacket对象,保存从客户端接收的数据
DatagramPacket packet=new DatagramPacket(data,0,data.length);
//此时处于阻塞状态,等待客户端请求
socket.receive(packet);
//创建一个新的线程
ServerThread serverThread=new ServerThread(socket,packet);
// 未设置优先级可能会导致运行时速度非常慢,可降低优先级
serverThread.setPriority(4);
//启动线程
serverThread.start();
//访问服务器的客户端的数量
count++;
System.out.println("当前访问服务器的客户端的数量为: "+count);
}
}
----------
UDPClientThread.java(客户端)
public static void main(String[] args) throws IOException {
/**
* 发送信息到服务器
* */
//1.定义发送的信息(服务器地址,端口号)
//定义服务器地址
InetAddress address=InetAddress.getByName("localhost");
//定义端口号
int port=8989;
//定义要发送的内容,要用字节来
byte[] data="用户名:李四;密码:123456".getBytes();
//2.创建DatagramPacket对象保存客户端要发送的数据
DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
//3.创建DatagramSocket发送数据
DatagramSocket socket=new DatagramSocket();
//4.发送数据
socket.send(packet);
/**
* 接收服务器响应的信息
* */
//1.创建DatagramPacket对象,接收服务器发送的信息
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2,0,data2.length);
//2.接收服务器发送的信息
socket.receive(packet2);
//3.读取服务器发送的信息
String info=new String(data2,0,packet.getLength());
System.out.println("我是客户端1,服务器说: "+info);
//4.关闭资源(千万不要忘记了)
socket.close();
}
Socket通信总结
1.多线程的优先级
2.关闭流问题与socket关闭问题
3.传递对象
4.传递文件
markdown编辑器快捷键
加粗
Ctrl + B
斜体
Ctrl + I
引用
Ctrl + Q
插入链接
Ctrl + L
插入代码
Ctrl + K
插入图片
Ctrl + G
提升标题
Ctrl + H
有序列表
Ctrl + O
无序列表
Ctrl + U
横线
Ctrl + R
撤销
Ctrl + Z
重做
Ctrl + Y
以上是关于Java中Socket网络通信的主要内容,如果未能解决你的问题,请参考以下文章
java 界面编程用socket实现服务端与客户端的循环通信。
Java Socket Server与Python客户端的通信,程序不会输入“inputLine = in.readLine()” - 循环