------------- android培训、java培训、java博客、java学习型技术博客、期待与您交流! --------------
1: 网络参考模型
2: 网络通讯要素
1: IP地址:InetAddress
•网络中设备的标识
•不易记忆,可用主机名
•本地回环地址:127.0.0.1 主机名:localhost
2: 端口号
•用于标识进程的逻辑地址,不同进程的标识
3:传输协议•有效端口:0~65535,其中0~1024系统使用或保留端口
•通讯的规则
•常见协议:TCP,UDP
3: TCP和UDP
UDP
•将数据及源和目的封装成数据包中,不需要建立连接
•每个数据报的大小在限制在64k内
•因无连接,是不可靠协议
•不需要建立连接,速度快
TCP
•建立连接,形成传输数据的通道。
•在连接中进行大数据量传输
•通过三次握手完成连接,是可靠协议
•必须建立连接,效率会稍低
4: Socket
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
5:UDP传输
1: DatagramSocket与DatagramPacket
2: 建立发送端,接收端。
3: 建立数据包。
4: 调用Socket的发送接收方法。
5: 关闭Socket。
1:用于接收:发送端与接收端是两个独立的运行程序。
DatagramPacket:数据报包,是UDP下进行传输数据的单位,数据存放在字节数组中,其中包括了目标地址和端口以及传送的信息。
DatagramPacket(byte[] buf , int length)
2:用于发送:
DatagramPacket(byte[] buf , int length , InetAddress address , int port )
6:UDP发送端
在发送端,要在数据包对象中明确目的地 IP及端口。
<span style="font-family:SimSun; font-size:12px">DatagramSocket ds = new DatagramSocket(); byte[] by = “hello,udp”.getBytes(); DatagramPacket dp = new DatagramPacket(by,0,by.length, InetAddress.getByName(“127.0.0.1”),10000); ds.send(dp); ds.close();</span>
7:UDP接收端
在接收端,要指定监听的端口。
<span style="font-family:SimSun; font-size:12px">DatagramSocket ds = new DatagramSocket(10000); byte[] by = new byte[1024]; DatagramPacket dp = new DatagramPacket(by,by.length); ds.receive(dp); String str = new String(dp.getData(),0,dp.getLength()); System.out.println(str+"--"+dp.getAddress()); ds.close();</span>
8: TCP传输
1: Socket和ServerSocket
2: 建立客户端和服务器端
3: 建立连接后,通过Socket中的IO流进行数 据的传输
4: 关闭socket
同样,客户端与服务器端是两个独立的应用 程序。
基本思路(客户端):
1:客户端需要明确服务器的ip地址以及端口,这样才 可以去试着建立连接,如果连接失败,会出现异 常。:
2:连接成功,说明客户端与服务端建立了通道,那么 通过IO流就可以进行数据的传输,而Socket对象已 经提供了输入流和输出流对象,通过 getInputStream(),getOutputStream()获取即可。
3:与服务端通讯结束后,关闭Socket
通过Socket建立对象并指定要连接的服务 端主机以及端口。
<span style="font-family:SimSun; font-size:12px">Socket s = new Socket(“192.168.1.1”,9999); OutputStream out = s.getOutputStream(); out.write(“hello”.getBytes()); s.close();</span>
基本思路(服务端)
1:服务端需要明确它要处理的数据是从哪个 端口进入的。:
2:当有客户端访问时,要明确是哪个客户 端,可通过accept()获取已连接的客户端 对象,并通过该对象与客户端通过IO流进 行数据传输。
3:当该客户端访问结束,关闭该客户端。
建立服务端需要监听一个端口
<span style="font-family:SimSun; font-size:12px">ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int num = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString()+”:”+str); s.close(); ss.close();</span>
9:Tcp传输最容易出现的问题
客户端连接上服务端,两端都在等待,没 有任何数据传输。
通过例程分析:
•因为read方法或者readLine方法是阻塞式。
解决办法:
•自定义结束标记
•使用shutdownInput,shutdownOutput方法。
10:URL
URL:网址,统一资源定位器
常用的构造器:
URL(String spec)
spec 一个完整的网址(协议+网址)
根据 String 表示形式创建 URL 对象。
URLConnection:与网址进行连接
通过URL的openConnection()方法生成一个URLConnection实例,通过下面两个方法,进行流的操作
1:getInputStream()
返回从此打开的连接读取的输入流
2:getOutputStream()
返回写入到此连接的输出流。
11:获取本机的IP地址:
<span style="font-family:SimSun; font-size:12px"> final JButton button = new JButton(); button.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { try { InetAddress inetAddr = InetAddress.getLocalHost();// 创建本地主机的InetAddress对象 String ip = inetAddr.getHostAddress();// 获得本地主机的IP地址 tf_ip.setText(ip);// 在文本框中显示IP地址 } catch (UnknownHostException e1) { e1.printStackTrace(); } } });</span>
12:获取本机的域名和主机名
<span style="font-family:SimSun; font-size:12px"> final JButton button = new JButton(); button.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { try { InetAddress inetAddr = InetAddress.getLocalHost();// 创建本地主机的InetAddress对象 String canonical = inetAddr.getCanonicalHostName();// 获取本地主机的域名 String host = inetAddr.getHostName();// 获取本地主机的主机名 tf_canonical.setText(canonical);// 在文本框中显示本地主机的域名 tf_host.setText(host);// 在文本框中显示本地主机的主机名 } catch (UnknownHostException e1) { e1.printStackTrace(); } } });</span><pre name="code" class="java"> public void gainAllIp() throws Exception {// 获得所有IP,并显示在文本域中的方法 InetAddress host = InetAddress.getLocalHost();// 获得本机的InetAddress对象 String hostAddress = host.getHostAddress();// 获得本机的IP地址 int pos = hostAddress.lastIndexOf(".");// 获得IP地址中最后一个点的位置 String wd = hostAddress.substring(0, pos + 1);// 对本机的IP进行截取,获得网段 for (int i = 1; i <= 255; i++) { // 对局域网的IP地址进行遍历 String ip = wd + i;// 生成IP地址 PingIpThread thread = new PingIpThread(ip);// 创建线程对象 thread.start();// 启动线程对象 } Set<String> set = pingMap.keySet();// 获得集合中键的Set视图 Iterator<String> it = set.iterator();// 获得迭代器对象 while (it.hasNext()) { // 迭代器中有元素,则执行循环体 String key = it.next(); // 获得下一个键的名称 String value = pingMap.get(key);// 获得指定键的值 if (value.equals("true")) { ta_allIp.append(key + "\n");// 追加显示IP地址 } } }
13: 通过IP地址获得域名和主机名:
<span style="font-family:SimSun; font-size:12px"> final JButton button = new JButton(); button.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { try { InetAddress inetAddr = InetAddress.getLocalHost();// 创建本地主机的InetAddress对象 String canonical = inetAddr.getCanonicalHostName();// 获取本地主机的域名 String host = inetAddr.getHostName();// 获取本地主机的主机名 tf_canonical.setText(canonical);// 在文本框中显示本地主机的域名 tf_host.setText(host);// 在文本框中显示本地主机的主机名 } catch (UnknownHostException e1) { e1.printStackTrace(); } } });</span>
14: 获得内网的所有IP地址:
首先获得本机Ip地址所在的网段,然后ping 网络中的Ip地址,通过输入流读取ping的结果。
public void gainAllIp() throws Exception {// 获得所有IP,并显示在文本域中的方法 InetAddress host = InetAddress.getLocalHost();// 获得本机的InetAddress对象 String hostAddress = host.getHostAddress();// 获得本机的IP地址 int pos = hostAddress.lastIndexOf(".");// 获得IP地址中最后一个点的位置 String wd = hostAddress.substring(0, pos + 1);// 对本机的IP进行截取,获得网段 for (int i = 1; i <= 255; i++) { // 对局域网的IP地址进行遍历 String ip = wd + i;// 生成IP地址 PingIpThread thread = new PingIpThread(ip);// 创建线程对象 thread.start();// 启动线程对象 } Set<String> set = pingMap.keySet();// 获得集合中键的Set视图 Iterator<String> it = set.iterator();// 获得迭代器对象 while (it.hasNext()) { // 迭代器中有元素,则执行循环体 String key = it.next(); // 获得下一个键的名称 String value = pingMap.get(key);// 获得指定键的值 if (value.equals("true")) { ta_allIp.append(key + "\n");// 追加显示IP地址 } } }
</pre><p></p></blockquote><p><span style="font-family:SimSun; font-size:12px"></span></p><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:SimSun; font-size:12px"></span></p><pre name="code" class="java">class PingIpThread extends Thread {// 判断给定IP是否为内网IP的线程对象 public String ip; // 表示IP地址的成员变量 public PingIpThread(String ip) {// 参数为需要判断的IP地址 this.ip = ip; } public void run() { try { // 获得所ping的IP进程,-w 280是等待每次回复的超时时间,-n 1是要发送的回显请求数 Process process = Runtime.getRuntime().exec( "ping " + ip + " -w 280 -n 1"); InputStream is = process.getInputStream();// 获得进程的输入流对象 InputStreamReader isr = new InputStreamReader(is);// 创建InputStreamReader对象 BufferedReader in = new BufferedReader(isr);// 创建缓冲字符流对象 String line = in.readLine();// 读取信息 while (line != null) { if (line != null && !line.equals("")) { if (line.substring(0, 2).equals("来自") || (line.length() > 10 && line.substring(0, 10) .equals("Reply from"))) {// 判断是ping通过的IP地址 pingMap.put(ip, "true");// 向集合中添加IP } } line = in.readLine();// 再读取信息 } } catch (IOException e) { } } }
15: 获取网络资源的大小:
public long netSourceSize(String sUrl) throws Exception{ URL url = new URL(sUrl); // 创建URL对象 URLConnection urlConn = url.openConnection(); // 获得网络连接对象 urlConn.connect(); // 打开到url引用资源的通信链接 return urlConn.getContentLength(); // 以字节为单位返回资源的大小 }
16: 解析网页中的内容:
public Collection<String> getURLCollection(String urlString){ URL url = null; // 声明URL URLConnection conn = null; // 声明URLConnection Collection<String> urlCollection = new ArrayList<String>(); // 创建集合对象 try{ url = new URL(urlString); // 创建URL对象 conn = url.openConnection(); // 获得连接对象 conn.connect(); // 打开到url引用资源的通信链接 InputStream is = conn.getInputStream(); // 获取流对象 InputStreamReader in = new InputStreamReader(is,"UTF-8"); // 转换为字符流 BufferedReader br = new BufferedReader(in); // 创建缓冲流对象 String nextLine = br.readLine(); // 读取信息,解析网页 while (nextLine !=null){ urlCollection.add(nextLine); // 解析网页的全部内容,添加到集合中 nextLine = br.readLine(); // 读取信息,解析网页 } }catch(Exception ex){ ex.printStackTrace(); } return urlCollection; }
17: 网络资源单线程下载:
public void download(String urlAddr){ // 从指定网址下载文件 try { URL url = new URL(urlAddr); // 创建URL对象 URLConnection urlConn = url.openConnection(); // 获得连接对象 urlConn.connect(); // 打开到url引用资源的通信链接 InputStream in = urlConn.getInputStream() ; // 获得输入流对象 String filePath = url.getFile(); // 获得完整路径 int pos = filePath.lastIndexOf("/"); // 获得路径中最后一个斜杠的位置 String fileName = filePath.substring(pos+1); // 截取文件名 FileOutputStream out = new FileOutputStream("C:/"+fileName); // 创建输出流对象 byte[] bytes = new byte[1024]; // 声明存放下载内容的字节数组 int len = in.read(bytes); // 从输入流中读取内容 while (len != -1){ out.write(bytes,0,len); // 将读取的内容写到输出流 len = in.read(bytes); // 继续从输入流中读取内容 } out.close(); // 关闭输出流 in.close(); // 关闭输入流 JOptionPane.showMessageDialog(null, "下载完毕"); } catch (Exception e) { e.printStackTrace(); } }
18: 演示tcp的传输的客户端和服务端的互访
class TcpClient2 { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.254",10004); OutputStream out = s.getOutputStream(); out.write("服务端,你好".getBytes()); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); } } class TcpServer2 { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10004); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"....connected"); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); OutputStream out = s.getOutputStream(); Thread.sleep(10000); out.write("哥们收到,你也好".getBytes()); s.close(); ss.close(); } }
19:需求:建立一个文本转换服务器。
客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。
而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。
*/ import java.io.*; import java.net.*; class TransClient { public static void main(String[] args) throws Exception { Socket s = new Socket("192.168.1.254",10005); //定义读取键盘数据的流对象。 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //定义目的,将数据写入到socket输出流。发给服务端。 //BufferedWriter bufOut = //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); //定义一个socket读取流,读取服务端返回的大写信息。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line); // bufOut.write(line); // bufOut.newLine(); // bufOut.flush(); String str =bufIn.readLine(); System.out.println("server:"+str); } bufr.close(); s.close(); } } /* 服务端: 源:socket读取流。 目的:socket输出流。 都是文本,装饰。 */ class TransServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10005); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"....connected"); //读取socket读取流中的数据。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。 //BufferedWriter bufOut = //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while((line=bufIn.readLine())!=null) { System.out.println(line); out.println(line.toUpperCase()); // bufOut.write(line.toUpperCase()); // bufOut.newLine(); // bufOut.flush(); } s.close(); ss.close(); } } /* 该例子出现的问题。 现象:客户端和服务端都在莫名的等待。 为什么呢? 因为客户端和服务端都有阻塞式方法。这些方法么没有读到结束标记。那么就一直等 而导致两端,都在等待。
------------- android培训、java培训、java博客、java学习型技术博客、期待与您交流! -------------
详情请查看:http://edu.csdn.net/heima/