javase_21(DUp的学习-->*)

Socket网络编程

 

网络协议

IP地址与端口号

本地回路IP: 127.0.0.1

有效端口:0-65535(尽量使用1024个以上-->1024个以上的被占用的概率比较低)

UDPTCP(协议)

Udp:用户数据包协议,面向无连接,不保证数据的可靠性,不安全,速度快

Tcp:传输数据协议,面向连接,提供可靠无差错的协议,安全,三次握手.

 

UDP传输:

DatagramSocket :DatagramPacket

建立发送端,接收端

建立数据包,

调用Socket的发送接收方法.

关闭Socket

发送端与接收端是两个独立运行的小程序.

 

 

发送端:

在发送端,要在数据包对象中明确的IP与端口.

 

DatagramSocket ds =
   new DatagramSocket();
 Byte[] by = "hello,net".getBytes();//转换成字节
 DatagramPacket dp = new DatagramPacket(by,0,by.length,InerAddress.getByName(127.0.0.1),10000); //数据包打包起来
 ds.send(dp);
 
 Ds.close();//关流


接收端:要指定监听的端口

datagramSocket ds = new datagramSocket(10000);
 byte [] buf = new byte[1024];
 datagramPacket dp = new datagramPacket(buf,by.length);
 ds.receive(dp);//把内容接收到dp里面去
 String str = new String(dp,getData(),0,dp.length());
 System.out.println(str);
 ds.close();


 

UDP聊天程序

通过键盘录入获取要发送的消息.

 

1 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
2 br.readLine();


将发送和接收分别封装到两个线程中,main()线程和 new Thread()线程

 

 

发送端:
 import java.net.DatagramSocket;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 class UdpSend
 {
     public static void main(String[]args)
     {
         DatagramSocket ds = null;
         try
         {
             ds = new DatagramSocket();
             String line = "I Come as For China";
             byte[]buf = line.getBytes();//转换成字节数组
             DatagramPacket dp = 
                     new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);
             ds.send(dp);
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }finally
         {
             if(ds!=null)
                 ds.close();//关闭流
         }
 
     }
 }
 
 接收端: 当开始监听端口的时候,会出现阻塞,直到监听完毕:
 import java.net.DatagramSocket;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 class UdpReceive 
 {
     public static void main(String[] args) 
     {
         //监听该端口
         DatagramSocket ds = null;
         try
         {
             ds = new DatagramSocket(8888);
             DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
             //它会发生阻塞功能,首先运行这个.他会监听端口 ..
             ds.receive(dp);
             byte[] buf = dp.getData();
             String data = new String(buf,0,dp.getLength());
             System.out.println(data);
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }finally
         {
             if(ds!=null)
                 ds.close();
         }
         
     }
 }


使用了循环的聊天方式(必须要开两个窗口)

 

发送端:()
 import java.net.DatagramSocket;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 class MySend
 {
     public static void main(String[] args) 
     {
         DatagramSocket ds = null;
         BufferedReader br = null;
         try
         {
             ds = new DatagramSocket();
             DatagramPacket dp;
             br = new BufferedReader(new InputStreamReader(System.in));
             System.out.println("聊一下吧~~~");
             while(true)
             {
                 String line = br.readLine();
                 if("byte".equals(line))break;//如果return;就关闭不了流啦
                 byte[] buf = line.getBytes(); //必须要获取到正确的长度
                 dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);//封装数据
                 ds.send(dp);
             }
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }finally
         {
             try
             {
                 if(ds!=null)
                     ds.close();
             }finally
             {
                 try
                 {
                     if(br!=null)
                         br.close();    
                 }catch(IOException e)
                 {
                     e.printStackTrace();
                 }
             }
         }
 
     }
 }
 
 接收端:
 import java.net.DatagramSocket;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 class MyReceive 
 {
     public static void main(String[] args) throws IOException 
     {
         DatagramSocket ds =  new DatagramSocket(8888);//监听端口号
         DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
         while(true)
         {
                 ds.receive(dp);//接收数据
                 String data = new String(dp.getData(),0,dp.getLength());
                 if("byte".equals(data))
                         break;
                 String ipHost = dp.getAddress().getHostName();//IP主机名字
                 String ipName = dp.getAddress().getHostAddress();//IP地址
                 int port = dp.getPort();
                 System.out.println(ipHost+"("+ipName+")"+" "+port);
                 System.out.println(data);
         }
         if(ds!=null)
                 ds.close();
     }
 }


-->我们需要做到的效果-->多线程实现.实现两边通信..

多线程的效果:

 

import java.net.DatagramSocket;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 class UdpChat 
 {
     /*
         利用多线程来实现程序
         Thread-0接收数据
         Main -主线程 发送数据
     */
     public static void main(String[] args) 
     {
         new Thread(new MyChat()).start();
         DatagramSocket ds = null;
         BufferedReader br = null;
         try
         {
             ds = new DatagramSocket();
             br = new BufferedReader(new InputStreamReader(System.in));
             System.out.println("咱们来聊一下吧~~~");
             while(true)
             {
                 String line = br.readLine();
                 if(line.equals("byte"))
                         break;
                 byte[] buf = line.getBytes();//转换成字节数组
                 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),9089);
                 ds.send(dp);
             }
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }
     }
 }
 
 class MyChat implements Runnable
 {
     public void run()
     {
         DatagramSocket ds = null;
         try
         {
             ds = new DatagramSocket(9089);
             DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
             while(true)
             {
                 ds.receive(dp);//接收数据
                 byte[] buf = dp.getData();
                 String line = new String(buf,0,dp.getLength());
                 String ipStr = dp.getAddress().getHostAddress()+"From:"+dp.getAddress().getHostName();//主机名字
                 int port = dp.getPort();
                 System.out.println(ipStr+port+" -- ~~"+line);
             }
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }finally
         {
             if(ds!=null)
                 ds.close();
         }
     }
 
 }


注意接收数据的时候会出现阻塞-->出现阻塞之后.您多线程怎么跑都运行不了.必须要等我发送端发送数据过去才可以.

1 获取时间:
2             String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
3                         + "\r\n" + data + "\r\n";


聊天程序案例分析
 一、需求
 1.软件的界面:实现窗体Frame、显示文本TextArea或List、发送按钮Button、IP输入TextField
 2.聊天功能:实现发送端和接收端程序(多线程)
 3.附加功能: 保存聊天记录、关闭软件
 
 二、实现步骤
 1.实现软件界面的设计
     1)创建Frame,设置大小、位置、可见 f
     2)创建一个TextArea文本域,用于显示文字 A
     3)创建一个TextArea文本域,用于输入文字 input
     3)创建一个TextField单行输入框用于输入Ip,B
     4)创建一个Button按钮,用于发送信息,C
 2.添加事件监听
     1)为f添加窗口监听addWindowListener(WindowAdapter),关闭窗口
     2)为按钮C添加鼠标监听 addMouseListener(MouseAdapter),监听点击事件,发送消息,调用sendMsg
     3)为文本域A添加键盘监听 addKeyListener(KeyAdapter) , 监听按下事件keyPressed发送消息 sendMsg
 
 3.实现发送端 sendMsg方法
     1)创建DatagramSocket对象,绑定闲置端口
     2)获取input中的内容,作为message
     3)获取B中的内容,作为Ip,这里要判断,如果没填,默认指定255.255.255.255
     4)创建DatagramPacket对象,打包数据,统一端口7888
     5)发送数据 ds.send(dp)
     6)将数据和时间显示在A,append方法
 4.实现接收端程序
     1)软件已运行就可以收数据了,所以在构造函数中开启新线程,运行接收端 new Thread(new Runnble()).start();
     2)在run方法中实现接收端程序
     3)创建DatagramSocket对象,监听7888端口
     4)准备数据包
     5)接受数据,阻塞,这个要做在循环里面 ds.receive(dp)
     6)获得数据和对方的Ip  , new String(dp.getData(), 0, dp.getLength())\dp.getInetAddress().getHostAddress\(dp.getPort)
     7)获得当前时间, DateFormat.getInstance().format(new Date());
     8)将数据显示在A,append方法
     
 
 
 import java.awt.BorderLayout;
 import java.awt.Button;
 import java.awt.Frame;
 import java.awt.Panel;
 import java.awt.TextArea;
 import java.awt.TextField;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.text.DateFormat;
 import java.util.Date;
 
 class MyChatTest 
 {
     public static void main(String[] args) 
     {
         MyChatOne mc = new MyChatOne();
     }
 }
 
 class MyChatOne
 {
     private Frame f;
     private TextArea disPlay,dataInput;
     private TextField ipInput;//IP地址的读取(单行文本可编程的组件)
     private Button senBtn;
     private boolean close = false;
     public MyChatOne()
     {
         f = new Frame();
         f.setSize(370,500);
         f.setLocation(100,150);
         f.setResizable(false);//不可移动
         disPlay = new TextArea(23,30);
         disPlay.setEditable(false);//不可编辑
         dataInput = new TextArea(10,30);
         ipInput = new TextField(20);
         senBtn = new Button("发送(Ctrl+Enter)");
         
         f.add(disPlay,"North");
         f.add(dataInput,"Center");
         Panel p = new Panel(new BorderLayout());
         p.add(ipInput,"West");//西边
         p.add(senBtn,"East");//北'
         f.add(p,"South");//南
         f.setVisible(true);
         handEvent();
         new Thread(new ReceiveInMyChat()).start();
     }
 
     //监听
     private void handEvent()
     {
         f.addWindowListener(new WindowAdapter(){
         public void windowClosing(WindowEvent e)
         {
             e.getWindow().dispose();
             close = true;
             ipInput.setText("127.0.0.1");//阻塞,随便运行一下发送端就可以.
         }
         });
         senBtn.addMouseListener(new MouseAdapter(){
         public void mouseClicked(MouseEvent e)
         {
             sendMsg();//当您触发我的确定按钮.我需要做的事情..
         }
         });
         dataInput.addKeyListener(new KeyAdapter(){
         //监听编辑器.当按下键盘并且+回车..你懂的..
         public void keyPressed(KeyEvent e)
             {
                 if(e.isControlDown()&&e.getKeyChar()=='\n')
                     sendMsg();
             }
         });
             
 
     }
 
     private void sendMsg()
     {
         //实现发送端的程序
         DatagramSocket ds = null;
         try
         {
             ds = new DatagramSocket();
             String data = dataInput.getText();//获取里面的数据
             String ip = ipInput.getText();//获取单行编辑条的内容
             if(ip.length()==0)
             {
                 ip = "127.0.0.1";
                 ipInput.setText(ip);//如果没有.我也必须往里面写入数据
             }
             byte[] buf = data.getBytes();//获取字节数组
 
             //封包
             DatagramPacket dp = 
                     new DatagramPacket(buf,buf.length,InetAddress.getByName(ip),8888);//封装数据
             //发包
             ds.send(dp);
             //将信息显示在display()这边
             String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
                         + "\r\n" + data + "\r\n";
             disPlay.append(str);//追加内容到这边来
             dataInput.setText("");//表示清空内容~
             saveMessage(str);
             //等一下我们可以做一下聊天记录
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }finally
         {
             if(ds!=null)
                 ds.close();
         }
     }
 
         //接收端咱们用多线程实现
     class ReceiveInMyChat implements Runnable
     {
         @Override
         public void run()
         {
             DatagramSocket ds = null;
             try
             {
                 ds = new DatagramSocket(8888);//指定需要监听的端口号
                 DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
                 while(true)
                 {
                     //阻塞-->必须要执行内容才可以到这一步.但我们到这一步.可以把多线程退出.
                     ds.receive(dp);
                     if(close)
                             break;//跳出循环.多线程就会关闭    
                     String data = new String(dp.getData(),0,dp.getLength());
                     String ip = dp.getAddress().getHostAddress()+"("+dp.getAddress().getHostName()+")";
                     String str = ip + "  发送于  " + DateFormat.getInstance().format(new Date())
                                     + "\r\n" + data + "\r\n";
                     disPlay.append(str);
                     saveMessage(str);
                 }
             }
             catch (IOException e)
             {
                 e.printStackTrace();
             }finally
             {
                 if(ds!=null)
                     ds.close();
             }
         }
     }
 
     
     /*
         聊天记录的保存:    
     */
     private void saveMessage(String str)
     {
         FileWriter fw = null;
         try
         {
             fw = new FileWriter("d:/聊天记录.txt",true);//表示从后面追加
             fw.write(str);
         }
         catch (IOException e)
         {
             e.printStackTrace();
         }
         finally
         {
             try
             {
                 if(fw!=null)
                     fw.close();//关流.
             }
             catch (IOException e)
             {
                 e.printStackTrace();
             }
         }
     }
 }
 
 
 多线程的回顾:
 package com.javami.kudyDemo.udpStudy;
 
 public class ThreadDemo {
 
     /**
      * 主要内容复习下多线程的回归,..主线程必须执行先~~
      */
     public static void main(String[] args) {
         new Thread(new MyThread()).start();
         for(int i=0; i<10; i++)
         {
             System.out.println("主线程!!!");
         }
     }
 
 }
 
 class MyThread implements Runnable
 {
     public void run()
     {
         int num = 0;
         while(true)
         {
             System.out.println("To Learn How");
             num ++;
             if(num>10)
                     break;
         }
     }
 }


心得与总结:

多线程需要复习-->

首先在接收数据的时候.会遇到阻塞-->必须要运行一下发送端程序..

时间这个类也得复习..

明天早上起来的任务-->必须要回顾知识..和敲写多一次这个程序.

今天的时间掌握得还是比较不好的~~希望下次好好努力改正..需要认真去对待每一件事..

多背下单词.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值