java网络编程

------------- android培训java培训、java博客、java学习型技术博客、期待与您交流! --------------



1: 网络参考模型

         


2: 网络通讯要素

1: IP地址:InetAddress

•网络中设备的标识

•不易记忆,可用主机名

•本地回环地址:127.0.0.1 主机名:localhost

2: 端口号

•用于标识进程的逻辑地址,不同进程的标识

•有效端口:0~65535,其中0~1024系统使用或保留端口


3:传输协议

•通讯的规则

•常见协议: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。

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


DatagramPacket:数据报包,是UDP下进行传输数据的单位,数据存放在字节数组中,其中包括了目标地址和端口以及传送的信息。

1:用于接收:
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/



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值