Socket编程
通信基础:ip地址(位置)、协议(语言)、端口(软件程序);
java提供网络功能的四大类:
InetAddress没有构造函数,不够里面有一些方法是可以返回实例,如:
InetAddress.getLocalHost();返回本机的实例;
InetAddress.getByName(String NAME);根据主机名或ip返回实例;
URL类实例化后可以获取URL的主机名、端口、文件的路径、文件名等等信息,需要注意的是,如果URL在实例化时没有指定端口号,会传入默认端口号,通过url.getPort()获取的端口号是-1而不是80;
URL提供了一个openStream(),用来获取URL的输入流,例:
public void urlTest() throws IOException { URL baidu = new URL("http://www.baidu.com"); InputStream in = baidu.openStream();//获取URL的输入流,此时输入流是字节数组 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(); }
给予TCP协议实现网络通信的类:
客户端:Socket类
服务器端;ServerSocket类
Socket实现通信的步骤:
常用的创建构造方法及常用方法:
ServerSocket类:
构造方法:
ServerSocket(int port);指定端口号创建ServerSocket类;
调用方法:
accept();监听并接收此套接字的连接,返回一个Socket;
close();关闭套接字
getInetAddress(),返回InetAddress类,返回服务器的本地地址;
getLocalPort(),返回int类,返回套接字监听的接口;
Socket类:
构造方法:
Socket(String host,int port);指定主机地址和端口创建Socket类;
调用方法;
close();关闭套接字
getInetAddress(),返回InetAddress类,返回套接字的本地地址;
getLocalPort(),返回int类,返回套接字绑定的接口;
getInputStream(),返回InputStream类,获取套接字的输入流
getOutputStream(),返回OutputStream类,获取套接字的输出流
通过Socket编码演示实现服务器端和客户端之间的通讯:
服务器端:
package com.Socket; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class server { public static void main(String[] args) throws IOException { ServerSocket serversocket = new ServerSocket(8889);//创建服务器套接字 System.out.println("===服务器即将启动,正在等待客户端的连接==="); Socket socket = serversocket.accept();//开始监听,等待客户端的连接 InputStream in = socket.getInputStream();//获取输入流 InputStreamReader inr = new InputStreamReader(in);//将字节输入流转为字符输入流 BufferedReader binr = new BufferedReader(inr);//将输入流添加到缓冲流 String info =null; while((info = binr.readLine())!=null) { System.out.println("我是服务器,客户端说:"+info); } socket.shutdownInput(); OutputStream output = socket.getOutputStream(); PrintWriter pw = new PrintWriter(output); pw.write("欢迎您"); pw.flush(); pw.close(); binr.close(); inr.close();in.close(); socket.close(); serversocket.close(); } }
客户端:
package com.Socket; import java.io.BufferedInputStream; 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) throws UnknownHostException, IOException { Socket socket = new Socket("localhost",8889);//创建客户端Socket套接字 OutputStream output = socket.getOutputStream();//创建字节输出流 PrintWriter pw = new PrintWriter(output);//将输出流包装为打印流 pw.write("用户名:admin;密码:123"); pw.flush(); socket.shutdownOutput(); InputStream in = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String info; while((info = br.readLine())!=null) { System.out.print("客户端对我说:"+info); } br.close(); in.close(); pw.close(); output.close(); socket.close(); } }
多线程的通信:
建立一个线程类:
package com.Socket; 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 { Socket socket = null; public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { InputStream in = socket.getInputStream();//获取输入流 InputStreamReader inr = new InputStreamReader(in);//将字节输入流转为字符输入流 BufferedReader binr = new BufferedReader(inr);//将输入流添加到缓冲流 String info =null; while((info = binr.readLine())!=null) { System.out.println("我是服务器,客户端说:"+info); } socket.shutdownInput(); OutputStream output = socket.getOutputStream(); PrintWriter pw = new PrintWriter(output); pw.write("欢迎您"); pw.flush(); if(pw!=null) pw.close(); if(binr!=null) binr.close(); if(inr!=null) inr.close(); if(in!=null) in.close(); if(socket!=null) socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
在服务器类中循环调用accept()方法并不断实例化线程类,在accept()连接返回一个Socket后又继续调用进行监听:
package com.Socket; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class server { public static void main(String[] args) throws IOException { ServerSocket serversocket = new ServerSocket(8889);//创建服务器套接字 Socket socket = null; int count = 0; System.out.println("===服务器即将启动,正在等待客户端的连接==="); while(true) { socket = serversocket.accept(); //开始监听,等待客户端的连接 ServerThread serverthread = new ServerThread(socket); serverthread.start(); count++; System.out.println("客户端的数量:"+count); InetAddress address =socket.getInetAddress(); System.out.println("客户端的IP:"+address); } } }
这样既可实现多客户端的多次连接;
UDP信息传输
DatagramPacket:表示数据报包
DatagramSocket:表示端到端通信的类
服务器端:
package com.Socket; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class Udpserver { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(8887);//创建Socket 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); //向客户端相应数据 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(); } }
客户端:
package com.Socket; 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 adress = InetAddress.getByName("localhost"); int port = 8887; byte[] data = "用户名:admin;密码:123".getBytes();//定义发送信息并存到字节数组中 DatagramPacket packet =new DatagramPacket(data,data.length,adress,port);//将定义好的字节数组和传送的目标地址,目标端口封装成数据报 DatagramSocket socket = new DatagramSocket();//创建socket套接字 socket.send(packet);//发送数据报 byte[] data3 = new byte[1024]; DatagramPacket packet3 =new DatagramPacket(data3,data3.length); socket.receive(packet3); String info2 = new String(data3,0,packet3.getLength()); System.out.println("服务器对我说:"+info2); socket.close(); } }