----------android培训、java培训、java学习型技术博客、期待与您交流! -----------
1,UDP协议
UDP俗称用户数据报协议,它的特点是:
UDP协议是面向非连接的协议,主要应用在数据传输要求通信效率较高的场合,不需要事先进行连接,传输的数据量也比较小,但是可靠性较小。
UDP中两个重要的类是DatagramSocket,DatagramPacket,它们的特点如下
1, 构造方法中凡是带有IP和PORT的DatagramPacket的数据报包都是用来发送的数据报包,否则都是用于接收的数据报包。
2, DatagramSocket仅仅负责数据的发送和接收,而对数据的封装工作全部由DatagramPacket类的构造进行了封装。
因此DatagramSocket仅仅负责从本机发出数据或者在本机接受数据。
因此DatagramSocket的构造方法仅仅涉及本机IP和端口号的传参。
由于Socket本身位于本机的App上面,因此就算不指定本机的IP或者端口,系统也会根据内部的参数自动获取到本机的IP或者App对象的端口号。
因此,可以有空参数的构造函数
3, DatagramPacket如果是在发送端,则要指明发送的目的地址和对应的端口号,如果在接受端,则不需要
DatagramSocket用于发送和接受数据,不过需要指明源地址和对应的端口
4, DatagramSocket主要有两种方法sen和receive,参数是DatagramPacket
示例代码:
发送端:
/*
需求:通过UDP传输方式,将一段文字数据发送出去
思路:
1.建立UDPSocket服务,即建立端点
2.提供数据,并将其封装到数据报包中
3.通过Socket服务的发送功能,将数据报发送出去
4.关闭资源
*/
class UdpSend{
public static void main(String[] args) throws Exception{
//1.创建UDP服务。通过DatagramSocket建立
DatagramSocket ds =new DatagramSocket();
//2.确定数据并封装成数据包
byte[] buf ="UDP is coming...".getBytes();
DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
//3.通过Socket服务将已有数据通过send方法发送出去
ds.send(dp);
//4.关闭资源
ds.close();
}
}
接收端:
/*
* 需求: 定义一个App用于接收通过UDP协议传输过来的数据
思路: 1,UDP接收端的操作流程
2,建立UDPSocket服务,即建立Socket接收端点。
3,定义一个数据报包。因为要存储接收到通过UDP传输来的字节数据,并且接收到的数据有很多信息。
如果自行提取会非常麻烦。因此直接封装成数据报包对象,调用该对象不同的方法从而获取接收到的数据报包中的信息。
(直接利用DataPacket类的JavaBean的Getter方法获取各种信息)
4,通过UDP接收端的Socket的receive方法将接收到的数据取出,并存入已定义好的数据报包对象中。
5.关闭Socket资源。
* */
class UdpRece{
public static void main(String[] args) throws Exception{
//1、创建udp Socket服务,建立端点
DatagramSocket ds =new DatagramSocket(10000);
while(true){
//2、定义数据报包对象,用于接收发送过来的数据
byte[] buf =new byte[1024];
DatagramPacket dp =new DatagramPacket(buf, buf.length);
//3、通过udpSocket服务的receive方法将数据存入定义好的数据报包
ds.receive(dp);
//4、通过数据报包的方法来获取不同的方法
String ip =dp.getAddress().getHostAddress();
String data =new String(dp.getData(), 0,dp.getLength());
int port =dp.getPort();
System.out.println(ip+"::"+ data+ "::"+ port);
}
//5、关闭资源
//ds.close();
}
}
验证结果:(补充先开启接收端,在开发送端)
2,读取键盘录入
发送端可以发送键盘录入的信息给接收端。
发送端代码:
class udpsend1{
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10003);
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine())!=null){
if("886".equals(line)){
break;
}
byte[] buf =line.getBytes();
DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10004);
System.out.println(InetAddress.getLocalHost().toString());
ds.send(dp);
}
ds.close();
}
}
接收端代码:
class udpreceive1{
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10004);
while(true){
byte[] buf =new byte[1024];
DatagramPacket dp =new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getData().length);
System.out.println(ip+"::"+ data);
}
}
}
验证结果:
3,简单聊天程序,实现一个窗口显示
发送端代码:
class Send implements Runnable{
private DatagramSocket ds;
public Send(DatagramSocket ds){
this.ds =ds;
}
public void run(){
try{
//键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
String line =null;
while((line =bufr.readLine())!=null){
if("886".equals(line))
break;
byte[] buf =line.getBytes();
DatagramPacket dp =new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10002);
ds.send(dp);
}
ds.close();
}catch(Exception e){
throw new RuntimeException("Send Failure!");
}
}
}
接收端代码:
class Rece implements Runnable{
private DatagramSocket ds;
public Rece(DatagramSocket ds){
this.ds =ds;
}
public void run(){
try{
while(true){
byte[] buf =new byte[1024];
DatagramPacket dp =new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data =new String(dp.getData(), 0,dp.getLength());
System.out.println(ip+"::"+ data);
}
}catch(Exception e){
throw new RuntimeException("Receive Failure!");
}
}
}
调用函数:
class ChatDemo
{
public static void main(String[] main) throws Exception{
DatagramSocket sendSocket =new DatagramSocket();
DatagramSocket receSocket =new DatagramSocket(10002);
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
验证结果:
4,TCP协议
TCP协议是面向连接的协议,主要应用在数据传输要求完整性较高的场合,需要经过三次握手,才能进行通信传输的数据量一般较大,可靠性较高。
a,简单的数据传送
需求:给服务器端发送一个文本数据
class TcpClient{
public static void main(String[] args) throws Exception{
//1. 创建客户端Socket服务,指定目的主机和端口
Socket s =new Socket("127.0.0.1", 10003);
//2.为了发送数据,应该获取Socket中的输出流
OutputStream out =s.getOutputStream();
//3.写数据到输出流,并随网络发送到对应主机
out.write("TCP is coming....".getBytes());
//4.关闭Socket资源对应的流资源不用关闭
s.close();
}
}
需求:定义端接收数据,并打印在控制台上
class TcpServer{
public static void main(String[] args) throws Exception{
//1.建立服务器端Socket服务,并监听一个端口
ServerSocket ss =new ServerSocket(10003);
//2.通过accept方法来获取连接过来的客户端对象 Server端本身没有流
//必须使用客户端对象的流对象与客户端本身进行通讯
Socket s =ss.accept();
InputStream in =s.getInputStream();
//获取客户端的IP
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected!");
byte[] buf =new byte[1024];
int len =in.read(buf);
System.out.println(new String(buf, 0, len));
//客户端一定要关闭客户端的Socket对象
s.close();
ss.close();//服务器端对象的关闭操作是可选的
}
}
验证结果:
b,服务器循环读取客户端的输入信息
客户端:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("127.0.0.1",10005);
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while((line = bufr.readLine())!=null){
/*
* BufferedWriter使用比较麻烦需要写三句话,如果忘记,容许造成双卡现象
* 改用PrintWriter
* */
bufout.write(line);
bufout.newLine();
bufout.flush();
if("over".equals(line))
break;
}
BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = bufin.readLine();
System.out.println(str);
bufr.close();
s.close();
}
服务端:
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();
BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = bufin.readLine())!=null){
System.out.println(line);
if("over".equals(line))
break;
}
bufout.write("输入结束");
bufout.newLine();
bufout.flush();
s.close();
ss.close();
}
验证结果:
c,客户端上传文本文件
客户端代码:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("127.0.0.1",10006);
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("ReadIn.java")));
PrintWriter bufout = new PrintWriter(s.getOutputStream(),true);
String line = null;
while((line = bufr.readLine())!=null){
bufout.println(line);
}
s.shutdownOutput();
BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = bufin.readLine();
System.out.println(str);
bufr.close();
s.close();
}
服务端代码:
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10006);
Socket s = ss.accept();
PrintWriter pw = new PrintWriter(new FileOutputStream("data_serv.txt"),true);
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = in.readLine())!=null){
pw.println(line.toUpperCase());
}
out.println("上传成功");
pw.close();
s.close();
ss.close();
}
验证结果:
d,实现图片的上传
客户端:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("127.0.0.1", 10006);
BufferedInputStream bufin = new BufferedInputStream(new FileInputStream("test.png"));
BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream());
int len = 0;
byte[] buf = new byte[1024];
while((len = bufin.read(buf))!= -1){
out.write(buf, 0, len);
out.flush();
}
s.shutdownOutput();
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
len = in.read(buf);
System.out.println(new String(buf, 0, len));
bufin.close();
s.close();
}
服务端:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("127.0.0.1", 10006);
BufferedInputStream bufin = new BufferedInputStream(new FileInputStream("test.png"));
BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream());
int len = 0;
byte[] buf = new byte[1024];
while((len = bufin.read(buf))!= -1){
out.write(buf, 0, len);
out.flush();
}
s.shutdownOutput();
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
len = in.read(buf);
System.out.println(new String(buf, 0, len));
bufin.close();
s.close();
}
验证结果:
e,字符流的文件上传
客户端:
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.1.3", 10007);
BufferedReader bufr = new BufferedReader(new FileReader("ReadIn.java"));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line = null;
while((line = bufr.readLine())!= null){
out.println(line);
}
/*
* 传文件时,需要分析是否是文本,最主要的的一点需要关闭流
* shutdownOutput,否则服务器无法识别什么时候结束
* */
s.shutdownOutput();
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
line = in.readLine();
System.out.println(line);
bufr.close();
s.close();
}
服务端:
public class servDemo4 {
public static void main(String[] args) throws IOException {
getserve();
}
public static void getserve() throws IOException{
ServerSocket ss = new ServerSocket(10007);
while(true){
Socket s = ss.accept();
new Thread(new serv(s)).start();
}
}
}
class serv implements Runnable{
private Socket s;
private static int count = 0;
public serv(Socket s) {
this.s = s;
}
public void run() {
PrintWriter pw = null;
try {
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connetion");
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
pw = new PrintWriter(new FileWriter(ip+"("+(count++)+")"),true);
String line = null;
while((line = in.readLine())!= null){
pw.println(line);
}
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("用户ip为"+ip+"的文件上传成功");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.toString());
}finally{
pw.close();
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.toString());
}
}
}
}
验证结果:
5,TCP和UDP总结:
/*
* 1,常见的阻塞式方法:
IO流中的BufferedReader的readLine()方法
IO流中的InputStream的read(byte[])方法
UDP通信中的接收方的receive(Datagrampacket)方法
TCP通信中的服务器方的accept()方法
* 2,双卡现象分析
* 情况一:读取行时,没有添加newline()和flush()方法,导致另一方无法读行结束符,使用PrinterWriter就能解决情况一
* 情况二:读取整个文本时,读到文件结尾,返回的是EOF标记,客户端无法有效的关闭流,所以在while结束时,添加shutdownOutput,就可以
* 3,流的个数:
* 一般情况下客户端需要三个流以上,两个网络流封装在socket中,本地流挑选其一,
* 服务端需要至少两个流,网络流即可,处理客户端的数据,如果要存储和读取本地文件,则需要根据功能需求加入本地流
* 规律:
* 本地流: BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
* BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(system.out()));
* (System.setin(键盘,内存,硬盘),System.setout(显示器,内存,硬盘))
* 网络流: PrintWriter out = new PrintWriter(s.getOutputStream(),true);//文件操作加true,
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
* */