javase_21(DUp的学习-->*)

Socket网络编程

 

网络协议

IP地址与端口号

本地回路IP: 127.0.0.1

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

UDPTCP(协议)

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

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

 

UDP传输:

DatagramSocket :DatagramPacket

建立发送端,接收端

建立数据包,

调用Socket的发送接收方法.

关闭Socket

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

 

 

发送端:

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

 

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

 

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

 

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

 

UDP聊天程序

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

 

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

 

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

 

 

 1 发送端:
 2 import java.net.DatagramSocket;
 3 import java.io.IOException;
 4 import java.net.DatagramPacket;
 5 import java.net.InetAddress;
 6 class UdpSend
 7 {
 8     public static void main(String[]args)
 9     {
10         DatagramSocket ds = null;
11         try
12         {
13             ds = new DatagramSocket();
14             String line = "I Come as For China";
15             byte[]buf = line.getBytes();//转换成字节数组
16             DatagramPacket dp = 
17                     new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);
18             ds.send(dp);
19         }
20         catch (IOException e)
21         {
22             e.printStackTrace();
23         }finally
24         {
25             if(ds!=null)
26                 ds.close();//关闭流
27         }
28 
29     }
30 }
31 
32 接收端: 当开始监听端口的时候,会出现阻塞,直到监听完毕:
33 import java.net.DatagramSocket;
34 import java.io.IOException;
35 import java.net.DatagramPacket;
36 import java.net.InetAddress;
37 class UdpReceive 
38 {
39     public static void main(String[] args) 
40     {
41         //监听该端口
42         DatagramSocket ds = null;
43         try
44         {
45             ds = new DatagramSocket(8888);
46             DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
47             //它会发生阻塞功能,首先运行这个.他会监听端口 ..
48             ds.receive(dp);
49             byte[] buf = dp.getData();
50             String data = new String(buf,0,dp.getLength());
51             System.out.println(data);
52         }
53         catch (IOException e)
54         {
55             e.printStackTrace();
56         }finally
57         {
58             if(ds!=null)
59                 ds.close();
60         }
61         
62     }
63 }

 

 

 

 

 

 

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

 

 

 1 发送端:()
 2 import java.net.DatagramSocket;
 3 import java.io.IOException;
 4 import java.net.DatagramPacket;
 5 import java.net.InetAddress;
 6 import java.io.BufferedReader;
 7 import java.io.InputStreamReader;
 8 class MySend
 9 {
10     public static void main(String[] args) 
11     {
12         DatagramSocket ds = null;
13         BufferedReader br = null;
14         try
15         {
16             ds = new DatagramSocket();
17             DatagramPacket dp;
18             br = new BufferedReader(new InputStreamReader(System.in));
19             System.out.println("聊一下吧~~~");
20             while(true)
21             {
22                 String line = br.readLine();
23                 if("byte".equals(line))break;//如果return;就关闭不了流啦
24                 byte[] buf = line.getBytes(); //必须要获取到正确的长度
25                 dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);//封装数据
26                 ds.send(dp);
27             }
28         }
29         catch (IOException e)
30         {
31             e.printStackTrace();
32         }finally
33         {
34             try
35             {
36                 if(ds!=null)
37                     ds.close();
38             }finally
39             {
40                 try
41                 {
42                     if(br!=null)
43                         br.close();    
44                 }catch(IOException e)
45                 {
46                     e.printStackTrace();
47                 }
48             }
49         }
50 
51     }
52 }
53 
54 接收端:
55 import java.net.DatagramSocket;
56 import java.io.IOException;
57 import java.net.DatagramPacket;
58 import java.net.InetAddress;
59 import java.io.BufferedReader;
60 import java.io.InputStreamReader;
61 class MyReceive 
62 {
63     public static void main(String[] args) throws IOException 
64     {
65         DatagramSocket ds =  new DatagramSocket(8888);//监听端口号
66         DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
67         while(true)
68         {
69                 ds.receive(dp);//接收数据
70                 String data = new String(dp.getData(),0,dp.getLength());
71                 if("byte".equals(data))
72                         break;
73                 String ipHost = dp.getAddress().getHostName();//IP主机名字
74                 String ipName = dp.getAddress().getHostAddress();//IP地址
75                 int port = dp.getPort();
76                 System.out.println(ipHost+"("+ipName+")"+" "+port);
77                 System.out.println(data);
78         }
79         if(ds!=null)
80                 ds.close();
81     }
82 }

 

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

多线程的效果:

 

 1 import java.net.DatagramSocket;
 2 import java.io.IOException;
 3 import java.net.DatagramPacket;
 4 import java.net.InetAddress;
 5 import java.io.BufferedReader;
 6 import java.io.InputStreamReader;
 7 import java.io.BufferedReader;
 8 import java.io.InputStreamReader;
 9 class UdpChat 
10 {
11     /*
12         利用多线程来实现程序
13         Thread-0接收数据
14         Main -主线程 发送数据
15     */
16     public static void main(String[] args) 
17     {
18         new Thread(new MyChat()).start();
19         DatagramSocket ds = null;
20         BufferedReader br = null;
21         try
22         {
23             ds = new DatagramSocket();
24             br = new BufferedReader(new InputStreamReader(System.in));
25             System.out.println("咱们来聊一下吧~~~");
26             while(true)
27             {
28                 String line = br.readLine();
29                 if(line.equals("byte"))
30                         break;
31                 byte[] buf = line.getBytes();//转换成字节数组
32                 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),9089);
33                 ds.send(dp);
34             }
35         }
36         catch (IOException e)
37         {
38             e.printStackTrace();
39         }
40     }
41 }
42 
43 class MyChat implements Runnable
44 {
45     public void run()
46     {
47         DatagramSocket ds = null;
48         try
49         {
50             ds = new DatagramSocket(9089);
51             DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
52             while(true)
53             {
54                 ds.receive(dp);//接收数据
55                 byte[] buf = dp.getData();
56                 String line = new String(buf,0,dp.getLength());
57                 String ipStr = dp.getAddress().getHostAddress()+"From:"+dp.getAddress().getHostName();//主机名字
58                 int port = dp.getPort();
59                 System.out.println(ipStr+port+" -- ~~"+line);
60             }
61         }
62         catch (IOException e)
63         {
64             e.printStackTrace();
65         }finally
66         {
67             if(ds!=null)
68                 ds.close();
69         }
70     }
71 
72 }

 

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

1 获取时间:
2             String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
3                         + "\r\n" + data + "\r\n";
  1 聊天程序案例分析
  2 一、需求
  3 1.软件的界面:实现窗体Frame、显示文本TextArea或List、发送按钮Button、IP输入TextField
  4 2.聊天功能:实现发送端和接收端程序(多线程)
  5 3.附加功能: 保存聊天记录、关闭软件
  6 
  7 二、实现步骤
  8 1.实现软件界面的设计
  9     1)创建Frame,设置大小、位置、可见 f
 10     2)创建一个TextArea文本域,用于显示文字 A
 11     3)创建一个TextArea文本域,用于输入文字 input
 12     3)创建一个TextField单行输入框用于输入Ip,B
 13     4)创建一个Button按钮,用于发送信息,C
 14 2.添加事件监听
 15     1)为f添加窗口监听addWindowListener(WindowAdapter),关闭窗口
 16     2)为按钮C添加鼠标监听 addMouseListener(MouseAdapter),监听点击事件,发送消息,调用sendMsg
 17     3)为文本域A添加键盘监听 addKeyListener(KeyAdapter) , 监听按下事件keyPressed发送消息 sendMsg
 18 
 19 3.实现发送端 sendMsg方法
 20     1)创建DatagramSocket对象,绑定闲置端口
 21     2)获取input中的内容,作为message
 22     3)获取B中的内容,作为Ip,这里要判断,如果没填,默认指定255.255.255.255
 23     4)创建DatagramPacket对象,打包数据,统一端口7888
 24     5)发送数据 ds.send(dp)
 25     6)将数据和时间显示在A,append方法
 26 4.实现接收端程序
 27     1)软件已运行就可以收数据了,所以在构造函数中开启新线程,运行接收端 new Thread(new Runnble()).start();
 28     2)在run方法中实现接收端程序
 29     3)创建DatagramSocket对象,监听7888端口
 30     4)准备数据包
 31     5)接受数据,阻塞,这个要做在循环里面 ds.receive(dp)
 32     6)获得数据和对方的Ip  , new String(dp.getData(), 0, dp.getLength())\dp.getInetAddress().getHostAddress\(dp.getPort)
 33     7)获得当前时间, DateFormat.getInstance().format(new Date());
 34     8)将数据显示在A,append方法
 35     
 36 
 37 
 38 import java.awt.BorderLayout;
 39 import java.awt.Button;
 40 import java.awt.Frame;
 41 import java.awt.Panel;
 42 import java.awt.TextArea;
 43 import java.awt.TextField;
 44 import java.awt.event.KeyAdapter;
 45 import java.awt.event.KeyEvent;
 46 import java.awt.event.MouseAdapter;
 47 import java.awt.event.MouseEvent;
 48 import java.awt.event.WindowAdapter;
 49 import java.awt.event.WindowEvent;
 50 import java.io.FileWriter;
 51 import java.io.IOException;
 52 import java.net.DatagramPacket;
 53 import java.net.DatagramSocket;
 54 import java.net.InetAddress;
 55 import java.net.SocketException;
 56 import java.text.DateFormat;
 57 import java.util.Date;
 58 
 59 class MyChatTest 
 60 {
 61     public static void main(String[] args) 
 62     {
 63         MyChatOne mc = new MyChatOne();
 64     }
 65 }
 66 
 67 class MyChatOne
 68 {
 69     private Frame f;
 70     private TextArea disPlay,dataInput;
 71     private TextField ipInput;//IP地址的读取(单行文本可编程的组件)
 72     private Button senBtn;
 73     private boolean close = false;
 74     public MyChatOne()
 75     {
 76         f = new Frame();
 77         f.setSize(370,500);
 78         f.setLocation(100,150);
 79         f.setResizable(false);//不可移动
 80         disPlay = new TextArea(23,30);
 81         disPlay.setEditable(false);//不可编辑
 82         dataInput = new TextArea(10,30);
 83         ipInput = new TextField(20);
 84         senBtn = new Button("发送(Ctrl+Enter)");
 85         
 86         f.add(disPlay,"North");
 87         f.add(dataInput,"Center");
 88         Panel p = new Panel(new BorderLayout());
 89         p.add(ipInput,"West");//西边
 90         p.add(senBtn,"East");//北'
 91         f.add(p,"South");//
 92         f.setVisible(true);
 93         handEvent();
 94         new Thread(new ReceiveInMyChat()).start();
 95     }
 96 
 97     //监听
 98     private void handEvent()
 99     {
100         f.addWindowListener(new WindowAdapter(){
101         public void windowClosing(WindowEvent e)
102         {
103             e.getWindow().dispose();
104             close = true;
105             ipInput.setText("127.0.0.1");//阻塞,随便运行一下发送端就可以.
106         }
107         });
108         senBtn.addMouseListener(new MouseAdapter(){
109         public void mouseClicked(MouseEvent e)
110         {
111             sendMsg();//当您触发我的确定按钮.我需要做的事情..
112         }
113         });
114         dataInput.addKeyListener(new KeyAdapter(){
115         //监听编辑器.当按下键盘并且+回车..你懂的..
116         public void keyPressed(KeyEvent e)
117             {
118                 if(e.isControlDown()&&e.getKeyChar()=='\n')
119                     sendMsg();
120             }
121         });
122             
123 
124     }
125 
126     private void sendMsg()
127     {
128         //实现发送端的程序
129         DatagramSocket ds = null;
130         try
131         {
132             ds = new DatagramSocket();
133             String data = dataInput.getText();//获取里面的数据
134             String ip = ipInput.getText();//获取单行编辑条的内容
135             if(ip.length()==0)
136             {
137                 ip = "127.0.0.1";
138                 ipInput.setText(ip);//如果没有.我也必须往里面写入数据
139             }
140             byte[] buf = data.getBytes();//获取字节数组
141 
142             //封包
143             DatagramPacket dp = 
144                     new DatagramPacket(buf,buf.length,InetAddress.getByName(ip),8888);//封装数据
145             //发包
146             ds.send(dp);
147             //将信息显示在display()这边
148             String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
149                         + "\r\n" + data + "\r\n";
150             disPlay.append(str);//追加内容到这边来
151             dataInput.setText("");//表示清空内容~
152             saveMessage(str);
153             //等一下我们可以做一下聊天记录
154         }
155         catch (IOException e)
156         {
157             e.printStackTrace();
158         }finally
159         {
160             if(ds!=null)
161                 ds.close();
162         }
163     }
164 
165         //接收端咱们用多线程实现
166     class ReceiveInMyChat implements Runnable
167     {
168         @Override
169         public void run()
170         {
171             DatagramSocket ds = null;
172             try
173             {
174                 ds = new DatagramSocket(8888);//指定需要监听的端口号
175                 DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
176                 while(true)
177                 {
178                     //阻塞-->必须要执行内容才可以到这一步.但我们到这一步.可以把多线程退出.
179                     ds.receive(dp);
180                     if(close)
181                             break;//跳出循环.多线程就会关闭    
182                     String data = new String(dp.getData(),0,dp.getLength());
183                     String ip = dp.getAddress().getHostAddress()+"("+dp.getAddress().getHostName()+")";
184                     String str = ip + "  发送于  " + DateFormat.getInstance().format(new Date())
185                                     + "\r\n" + data + "\r\n";
186                     disPlay.append(str);
187                     saveMessage(str);
188                 }
189             }
190             catch (IOException e)
191             {
192                 e.printStackTrace();
193             }finally
194             {
195                 if(ds!=null)
196                     ds.close();
197             }
198         }
199     }
200 
201     
202     /*
203         聊天记录的保存:    
204     */
205     private void saveMessage(String str)
206     {
207         FileWriter fw = null;
208         try
209         {
210             fw = new FileWriter("d:/聊天记录.txt",true);//表示从后面追加
211             fw.write(str);
212         }
213         catch (IOException e)
214         {
215             e.printStackTrace();
216         }
217         finally
218         {
219             try
220             {
221                 if(fw!=null)
222                     fw.close();//关流.
223             }
224             catch (IOException e)
225             {
226                 e.printStackTrace();
227             }
228         }
229     }
230 }
231 
232 
233 多线程的回顾:
234 package com.javami.kudyDemo.udpStudy;
235 
236 public class ThreadDemo {
237 
238     /**
239      * 主要内容复习下多线程的回归,..主线程必须执行先~~
240      */
241     public static void main(String[] args) {
242         new Thread(new MyThread()).start();
243         for(int i=0; i<10; i++)
244         {
245             System.out.println("主线程!!!");
246         }
247     }
248 
249 }
250 
251 class MyThread implements Runnable
252 {
253     public void run()
254     {
255         int num = 0;
256         while(true)
257         {
258             System.out.println("To Learn How");
259             num ++;
260             if(num>10)
261                     break;
262         }
263     }
264 }

 

心得与总结:

多线程需要复习-->

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

时间这个类也得复习..

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

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

多背下单词.

 

 

 

posted @ 2012-08-30 00:39  自学_更是一种信仰  阅读(319)  评论(0编辑  收藏  举报