Socket编程
1.InetAddress类
2.URL
3.TCP编程
4.UDP编程
详情参考相关JDK的API文档
1.InetAddress类
InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址
public class Test {
public static void main(String[] args) throws UnknownHostException {
//获取本机的InetAddress实例
InetAddress address=InetAddress.getLocalHost();
System.out.println("计算机名"+address.getHostName());
System.out.println("IP地址"+address.getHostAddress());
byte[] bytes=address.getAddress(); //获取字节数组形式的IP地址
System.out.println("字节数组形式IP地址"+Arrays.toString(bytes));
System.out.println(address);
//根据机器名获取InetAddress实例
InetAddress address2=InetAddress.getByName("DESKTOP-USC18G4");
System.out.println("计算机名"+address2.getHostName());
System.out.println("IP地址"+address2.getHostAddress());
//根据IP地址获取InetAddress实例
InetAddress address3=InetAddress.getByName("192.168.73.1");
System.out.println("计算机名"+address3.getHostName());
System.out.println("IP地址"+address3.getHostAddress());
}
}
结果:
计算机名DESKTOP-USC18G4
IP地址192.168.73.1
字节数组形式IP地址[-64, -88, 73, 1]
DESKTOP-USC18G4/192.168.73.1
计算机名DESKTOP-USC18G4
IP地址192.168.73.1
计算机名DESKTOP-USC18G4
IP地址192.168.73.1
2.URL
URL统一资源定位符,表示Internet上某一资源的地址,由协议名和资源名组成,中间用冒号隔开
在java.net包中,提供了URL类来表示URL
基本方法:
public class Test02 {
public static void main(String[] args) {
try {
URL baidu=new URL("http://www.baidu.com");
URL url=new URL(baidu,"/index.html?name=we#test");//#后面表示锚点
System.out.println("协议:"+url.getProtocol());
System.out.println("主机"+url.getHost());
//若未指定端口号,则使用默认端口号-1
System.out.println("端口"+url.getPort());
System.out.println("文件路径"+url.getPath());
System.out.println("文件名"+url.getFile());
System.out.println("相对路径"+url.getRef());
System.out.println("查询字符串"+url.getQuery());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
结果:
协议:http
主机www.baidu.com
端口-1
文件路径/index.html
文件名/index.html?name=we
相对路径test
查询字符串name=we
使用URL读取网页内容
通过URL对象的openStream方法可以得到指定资源的输入流
通过输入流可以读取或访问网络上的资源
public class Test03 {
public static void main(String[] args) {
try {
URL url=new URL("http://www.baidu.com");
//通过URL的openStream方法获取URL对象所表示的资源的字节输入流
InputStream is=url.openStream();
//将字节输入流转换成字符输入流
InputStreamReader isr=new InputStreamReader(is,"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();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta ht........................................
Socket通信
基于TCP协议实现网络通信有两个Socket类:
客户端的Socket类
服务器端的ServerSocket类
Socket通信模型
Socket实现步骤
1.创建ServerSocket和Socket
2.打开连接到Socket的输入/输出流
3.按照协议对Socket进行读/写操作
4.关闭输入输出流、关闭Socket
服务端具体步骤:
1.创建ServerSocket对象,绑定监听端口
2.通过accept()方法监听客户端请求
3.连接建立后,通过输入流读取客户端发送的请求信息
4.通过输出流向客户端发送响应信息
5.关闭相关资源
public class Server {
//基于TCP协议的Socket通信,实现用户登录
//服务器端
public static void main(String[] args) throws Exception {
//1.创建ServerSocket对象,绑定监听端口
ServerSocket serversocket=new ServerSocket(8888);
//2.通过accept()方法监听客户端请求
System.out.println("*****服务器即将启动,等待客户端连接*****");
Socket socket=serversocket.accept();
//3.连接建立后,通过输入流读取客户端发送的请求信息
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();//关闭输入流
//4.获取输出流,响应客户端
OutputStream os=socket.getOutputStream();
PrintWriter pe=new PrintWriter(os);
pe.write("欢迎你!");
pe.flush(); //刷新缓存,发送
//5.关闭相关资源
pe.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serversocket.close();
}
}
结果:
*****服务器即将启动,等待客户端连接*****
我是服务器,客户端说:用户名:admin,密码:123
客户端具体步骤:
1.创建Socket对象,指明需要连接的服务器的地址和端口号
2.连接建立后,通过输出流向服务器端发送请求信息
3.通过输入流获取服务器端响应的信息
4.关闭相关资源
public class Client {
//客户端
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket("localhost",8888);
//获取输出流,向服务器端发送消息
OutputStream out=socket.getOutputStream();
PrintWriter pe=new PrintWriter(out);
pe.write("用户名:admin,密码:123");
pe.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();
pe.close();
out.close();
socket.close();
}
}
结果:
我是客户端,服务器端说:欢迎你!
多线程实现多客户端通信
基本步骤:
1.服务器端创建SeverSocket,循环调用accept(),等待客户端连接
2.客户端创建一个Socket并请求和服务器端连接
3.服务器接收请求,创建Socket与该客户建立专线连接
4.建立的两个socket在一个单独的线程上对话
5.服务器端继续等待新连接
ServerThread类:
//服务器线程处理类
public class ServerThread extends Thread {
//和本线程相关的socket
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 pe=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();
pe=new PrintWriter(os);
pe.write("欢迎你!");
pe.flush(); //刷新缓存,发送
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭相关资源
try {
if(pe!=null)
pe.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();
}
}
}
}
Server类:
public class Server {
//基于TCP协议的Socket通信,实现用户登录
//服务器端
public static void main(String[] args) throws Exception {
//创建ServerSocket对象,绑定监听端口
ServerSocket serversocket=new ServerSocket(8888);
Socket socket=null;
int count=0; //记录客户端的数量
System.out.println("*****服务器即将启动,等待客户端连接*****");
while(true){
//通过accept()方法监听客户端请求
socket=serversocket.accept();
//创建一个新线程
ServerThread st=new ServerThread(socket);
st.start();
count++;
System.out.print("客户端的数量:"+count+" ");
InetAddress address=socket.getInetAddress();
System.out.println("当前客户端的IP地址:"+address.getHostAddress());
}
}
}
Client类:
public class Client {
//客户端
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket("localhost",8888);
//获取输出流,向服务器端发送消息
OutputStream out=socket.getOutputStream();
PrintWriter pe=new PrintWriter(out);
pe.write("用户名:Tony,密码:123");
pe.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();
pe.close();
out.close();
socket.close();
}
}
运行结果: 先启动Server,再启动多个Client,即可看到如下信息
*****服务器即将启动,等待客户端连接*****
客户端的数量:1 当前客户端的IP地址:127.0.0.1
我是服务器,客户端说:用户名:admin,密码:123
客户端的数量:2 当前客户端的IP地址:127.0.0.1
我是服务器,客户端说:用户名:Tony,密码:123
UDP编程
进行数据传输时,首先需要将传输的数据定义成数据报(Datagram),在数据报中指明数据所要到达的socket(主机地址和端口),发送数据报
相关操作类:
DatagramPacket:表示数据报包
DatagramSocket:进行端到端通信的类
服务端实现步骤:
1.创建DatagramSocket,指定端口号
2.创建DatagramPacket
3.接收客户端发送的数据信息
4.读取数据
public class UDPServer {
public static void main(String[] args) throws IOException {
//创建服务器端DatagramSocket,指定端口
DatagramSocket socket=new DatagramSocket(8800);
//创建数据报,用于接收客户端发送的数据
byte[] data=new byte[1024]; //指定接收的数据包的大小
DatagramPacket packet=new DatagramPacket(data,data.length);
//接收客户端发送的数据
System.out.println("******服务端启动,等待客户端发送数据*****");
socket.receive(packet); //此方法在接收到数据报之前会一直阻塞
//读取数据
String info=new String(data,0,packet.getLength());
System.out.println("我是服务器,客户端说:"+info);
//响应客户端
//得到客户端的IP,端口
InetAddress address=packet.getAddress();
int port=packet.getPort();
byte[] data2="欢迎你".getBytes();
DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port);
socket.send(packet2);
//关闭资源
socket.close();
}
}
结果:
******服务端启动,等待客户端发送数据*****
我是服务器,客户端说:用户名:admin,密码:123
客户端实现步骤:
1.定义发送信息
2.创建DatagramPacket,包含要发送的信息
3.创建DatagramSocket
4.发送数据
public class UDPClient {
//客户端
public static void main(String[] args) throws Exception {
InetAddress address=InetAddress.getByName("localhost");
int port=8800;
byte[] data="用户名:admin,密码:123".getBytes();
DatagramPacket packet=new DatagramPacket(data,data.length,address,port);
DatagramSocket socket=new DatagramSocket();
socket.send(packet);
//接收服务器响应数据
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2,data2.length);
socket.receive(packet2); //此方法在接收到数据报之前会一直阻塞
//读取数据
String info=new String(data2,0,packet2.getLength());
System.out.println("我是客户端,服务器说:"+info);
//关闭资源
socket.close();
}
}
结果:
我是客户端,服务器说:欢迎你