mooc_java Socket
Socket通信,TCP协议是面向连接,可靠的,有序的,以字节流的方式发送数据;
基于TCP协议实现网络通信的类
客户端的Socket类 服务器端的ServerSocket类
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
实现基于TCP的Socket通信:
在服务器端,创建ServerSocket对象,绑定监听端口;通过accept方法监听客户请求;建立连接后,通过输入流读取客户端发送的请求;通过输入流向客户端发送响应信息;关闭相关资源。
public class Server { public static void main(String[] args) { try { //创建一个服务器端Socket,指定绑定的端口, ServerSocket serverSocket=new ServerSocket(8888); //调用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(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
在客户端,创建Socket对象,指明要连接的服务器地址和端口号;建立连接后,通过输出流想服务器端发送请求信息;通过输入流获取服务器响应的信息;关闭相关资源。
public class Client { public static void main(String[] args) { try { //创建客户端Socket,指定服务器地址和端口 Socket socket=new Socket("localhost",8888); //获取输出流,向服务器发送信息 OutputStream os=socket.getOutputStream();//字节输出流 PrintWriter pw=new PrintWriter(os);//将输出流包装成打印流 pw.write("用户名:admin;密码:123"); pw.flush();//刷新缓存,向服务器端提供信息 socket.shutdownOutput();//关闭输出流 pw.close(); os.close(); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
服务器响应客户端:
//获取输入流,响应客户端的请求 OutputStream os=socket.getOutputStream(); PrintWriter pw=new PrintWriter(os);//包装为打印流 pw.write("欢迎您"); pw.flush();//调用flush方法将缓冲输出 pw.close(); os.close();
客户端:
//获取输入流,读取服务器端的响应信息 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();
使用多线程实现多客户端的通信:
ServerTherad类
public class ServerThread extends Thread{ Socket socket=null; public ServerThread(Socket socket){ this.socket=socket;//初始化和本线程相关的socket } //线程执行的操作,响应客户端的请求 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();//调用flush方法将缓冲输出 } catch (IOException e) { // TODO Auto-generated catch block 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) socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Server类
public class Server { public static void main(String[] args) { try { ServerSocket serverSocket=new ServerSocket(8888); 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.print("当前客户端的IP:"+address.getHostAddress()); } } catch (IOException e) { e.printStackTrace(); } } }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
实现基于UDP的Socket通信:
UDP协议(用户数据报协议)是无连接的,不可靠的,无序的,速度相对较快,以数据报作为数据传输的载体:
在进行数据传输时,将数据定义成数据报(Datagram),在数据报中致命数据要达到 的Socket(主机地址和端口号),然后发送数据报。
相关操作类:
DatagramPacket:数据报包 DatagramSocket:进行 端到端通信的类
服务器端:
创建DatagramSocket,指定端口号
创建DatagramPacket
接收客户端发送的数据信息
读取数据
客户端:
定义发送信息
创建DatagramPacket,包含要发送的信息
创建DatagramSocket
--------------------------
实现基于UDP的用户登录
服务器端要早于客户端启动
//服务器端 public static void main(String[] args) throws IOException { //1.创建服务器端DatagramSocket,指定端口 DatagramSocket socket=new DatagramSocket(8800); //2.创建数据报 byte[] data=new byte[1024];//穿件字节数组,指定接收的数据报的大小 DatagramPacket packet=new DatagramPacket(data, data.length); //3.接收客户端发送的数据 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.send(packet2); //4.关闭资源 socket.close(); }
//客户端 public static void main(String[] args) throws IOException { //1.定义服务器的地址,端口号,数据 InetAddress address=InetAddress.getByName("localhost"); int port=8800; byte[] data="用户名:admin;密码:123".getBytes();//转化成字节数组 //2.创建数据报,包含发送的数据信息 DatagramPacket packet=new DatagramPacket(data, data.length, address, port); //3.创建DatagramSocket对象 DatagramSocket socket=new DatagramSocket(); //4向服务器端发送数据报 socket.send(packet); /* * 接收服务器端响应的数据 */ //1.创建数据报,用于接收服务器端响应的数据 byte[] data2=new byte[1024]; DatagramPacket packet2=new DatagramPacket(data2, data2.length); //2.接收服务器端响应的数据 socket.receive(packet2);//接收并保存在packet2中 //3.读取信息 String reply=new String(data2, 0,packet2.getLength()); System.out.println("客户端:服务器"+reply); //4.关闭资源 socket.close(); }