udp:(对讲机,不管是否和对方链接成功,都能说话)
无连接
将数据源和目的封装成包
每个数据包的大小限制在64k
不可靠,数据会丢失
速度快
DataGramSocket表示发送端和接受端数据包的套接字,套接字类似插座,港口
模拟聊天窗口
Person1
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/** * * @author WangShuang * */public class Person1 { public static void main(String[] args) throws SocketException { Runnable sendDemo = new SendDemo(); Runnable receiveDemo = new ReceiveDemo(); new Thread(sendDemo).start(); new Thread(receiveDemo).start(); }}class SendDemo implements Runnable{ @Override public void run() { DatagramSocket dgs = null; try { InetAddress byName = InetAddress.getByName("ip地址"); //创建udpsocket服务 dgs = new DatagramSocket(); //确定方式数据,封装成数据包 while(true){ InputStream in = System.in; InputStreamReader isr = new InputStreamReader(in);//将字节输入流转成字符输入流 BufferedReader br = new BufferedReader(isr); String readLine = br.readLine(); byte[] data = readLine.getBytes(); DatagramPacket dgp = new DatagramPacket(data, data.length,localHost,10001); //通过udpsocket服务的发送功能,将数据包发送 dgs.send(dgp); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ dgs.close(); } }}class ReceiveDemo implements Runnable{ @Override public void run() { DatagramSocket dgs = null; try { //建立udpsocket服务,并未应用程序分配端口 dgs= new DatagramSocket(10000); //建立空数据包,存储接收到的数据, byte[] buf = new byte[1024]; DatagramPacket dgp = new DatagramPacket(buf, buf.length); while(true){ //通过socket服务的接受功能,接收数据 dgs.receive(dgp); //通过数据包的特有功能,将数据进行提取 String hostAddress = dgp.getAddress().getHostAddress(); int port = dgp.getPort(); byte[] data = dgp.getData(); String string = new String(data,0,dgp.getLength()); //处理数据 System.out.println(hostAddress+"..."+port+"..."+string); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ dgs.close(); } }}
Person2
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;public class Person2 { public static void main(String[] args) throws SocketException { DatagramSocket sendDatagramSocket = new DatagramSocket(); DatagramSocket receiveDatagramSocket = new DatagramSocket(10001); Runnable sendDemo = new SendDemo2(sendDatagramSocket); Runnable receiveDemo = new ReceiveDemo2(receiveDatagramSocket); new Thread(sendDemo).start(); new Thread(receiveDemo).start(); }}class SendDemo2 implements Runnable{ private DatagramSocket dgs; public SendDemo2(DatagramSocket dgs) { this.dgs = dgs; } @Override public void run() { try { InetAddress byName = InetAddress.getByName("ip地址"); //创建udpsocket服务 //确定方式数据,封装成数据包 while(true){ InputStream in = System.in; InputStreamReader isr = new InputStreamReader(in);//将字节输入流转成字符输入流 BufferedReader br = new BufferedReader(isr); String readLine = br.readLine(); byte[] data = readLine.getBytes(); DatagramPacket dgp = new DatagramPacket(data, data.length,localHost,10000); //通过udpsocket服务的发送功能,将数据包发送 dgs.send(dgp); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ dgs.close(); } }}class ReceiveDemo2 implements Runnable{ private DatagramSocket dgs; public ReceiveDemo2(DatagramSocket dgs) { this.dgs = dgs; } @Override public void run() { try { //建立udpsocket服务,并未应用程序分配端口 //建立空数据包,存储接收到的数据, byte[] buf = new byte[1024]; DatagramPacket dgp = new DatagramPacket(buf, buf.length); while(true){ //通过socket服务的接受功能,接收数据 dgs.receive(dgp); //通过数据包的特有功能,将数据进行提取 String hostAddress = dgp.getAddress().getHostAddress(); int port = dgp.getPort(); byte[] data = dgp.getData(); String string = new String(data,0,dgp.getLength()); //处理数据 System.out.println(hostAddress+"..."+port+"..."+string); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ dgs.close(); } }}
tcp(电话,只有和对方建立连接才能通话)
建立连接,形成传输数据的通道(socket流)
在链接中,可以进行一次性的大量数据的传输
链接通过3次握手完成的,在吗?在。知道了
数据相对慢
分为客户端(socket)和服务端(ServerSocket)
客户端
import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.InetAddress;import java.net.Socket;import java.net.SocketException;import java.net.UnknownHostException;/** * * @author WangShuang * */public class ClientDemo { public static void main(String[] args) throws SocketException { Socket socket = null; BufferedReader br=null; try { InetAddress byName = InetAddress.getByName("ip地址"); //创建客户端socket服务,指定目的主机和端口 socket = new Socket(byName,9999); //为了发送数据,应该获取socket流中的输出流,将数据写到该流中,通过网络发送给服务端 OutputStream outputStreamsocket = socket.getOutputStream(); //将socket输出流转成字符缓冲输出流 OutputStreamWriter oswsocket = new OutputStreamWriter(outputStreamsocket);//通过转换流将字节输出流转为字符输出流 BufferedWriter bwsocket = new BufferedWriter(oswsocket);//字符缓冲流 //读取键盘输入的数据,并转成字符缓冲流 br = new BufferedReader(new InputStreamReader(System.in)); String readLine = null; while((readLine=br.readLine())!=null){ //将键盘输入的数据,写到socket流中 bwsocket.write(readLine); bwsocket.newLine(); bwsocket.flush(); //获取socket输入流,将服务端的数据获取到,并打印 BufferedReader fbrsocket = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("服务端返回的数据"+fbrsocket.readLine()); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { br.close() //关闭客户端资源 socket.close(); } catch (IOException e) { e.printStackTrace(); } } }}
服务端
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.ServerSocket;import java.net.Socket;public class ServiceDemo { public static void main(String[] args) { //创建服务端socket服务 ServerSocket serverSocket=null; Socket socket =null; try { serverSocket = new ServerSocket(9999); //获取客户端socket对象 socket = serverSocket.accept(); //获取socket输入流,并转成字符缓冲输入流,将客户端的数据读取到,并打印 InputStream stream = socket.getInputStream(); BufferedReader brsocket = new BufferedReader(new InputStreamReader(stream)) ; String data = null; while((data=brsocket.readLine())!=null){ System.out.println("客户端发送的数据"+data); //反馈信息给客户端 BufferedWriter bwsockect = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())) ; bwsockect.write(data.toUpperCase()); bwsockect.newLine(); bwsockect.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }}
问题:为什么客户端关闭以后,服务端也关闭呢
因为客户端的socket已经关闭了,服务端是获取的客户端的socket,所以服务端也技术了
如果发生客户端和服务端程序都停止运行,那么就应该从readLine()方法入手,因为该方法是阻塞式方法,像缓冲区中写数据时是否刷新,是否有结束