黑马程序员——java基础知识之网络编程(二)

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
(一)网络编程的深入
1、基础知识总结:
①网络编程:主要是和IO流联系紧密,基本上有网络编程的地方,就有IO流的应用。
②当网络编程遇到一对多传输时,要利用多线程来处理
③小知识点:
游览器输入网址进行访问的时候,会先在本地的hosts文件(c:\windows\system32\drivers\ext\host)中找对应的映射。若有,则直接返回请求;若无,则到公网的映射列表即DNS中找对应的映射,找到后,将主机名对应的IP地址返回给本机,本机通过这个IP地址找到对应的服务器。
④网络编程主要要掌握UDP传输和TCP传输
UDP传输的步骤:
1)创建 UDPSocket发送服务对象:
DatagramSocket(),不指定端口。DatagramSocket(int port),指定端口。
2)发送:void send(DatagramPacket p)
3)接收:void receive(DatagramPacket p)
TCP传输的步骤:
客户端:
1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取
2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流
3)通过输出流的write()方法将要发送的数据写入到流中
4)关闭Socket流资源
服务端:
1)建立服务端的Socket服务,并监听一个端口。通过ServerSocet带端口参数的构造函数
2)获取连接过来的客户对象,通过ServerSocket的accept()方法,此方法是阻塞式的,如果服务端没有连接到就会一直等待
3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。
4)关闭服务端(可选)。一般服务端是常开的,因为在实际应用中,随时有客户端在请求连接和服务。但这里需要定时关闭客户端对象流,避免某一个客户端长时间占用服务器端。

2、网络编程的综合应用
例子1:利用网络编程实现图片上传

package cn.dhj;

import java.io.*;
import java.net.*;

/*
 * 需求:网络上传图片
 *客户端。
1,服务端点。
2,读取客户端已有的图片数据。
3,通过socket 输出流将数据发给服务端。
4,读取服务端反馈信息。
5,关闭。
 */

public class UploadPic {
    public static void main (String[] args) throws Exception{
        Socket s = new Socket("127.0.0.1",8888);
        FileInputStream fis = new FileInputStream("c:\\1.bmp");
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[2014];
        int len = 0;
        if((len=fis.read(buf))!=-1){
            out.write(buf , 0 ,len);
        }
        s.shutdownOutput();//告诉服务端数据已经写完,也就是做一个标记
        InputStream In = s.getInputStream();
        byte[] bufIn = new byte[2014];
        int read = In.read(bufIn);
        System.out.println(new String(bufIn,0,read));
    }
}
class UploadPicServer {
    public static void main (String[] args) throws Exception{
    ServerSocket ss = new ServerSocket(8888);
    Socket s =ss.accept();
    InputStream Inc = s.getInputStream();
    FileOutputStream outc = new FileOutputStream("server.bmp");
    byte[] buf = new byte[2014];
    int len = 0;
    while((len=Inc.read(buf))!=-1){
        outc.write(buf,0,len);
    }
    OutputStream out = s.getOutputStream();
    out.write("上传成功".getBytes());
    Inc.close();
    ss.close();
    s.close();
    }   
}

例子2、网络编程(TCP-客户端并发上传图片)

package cn.dhj;

import java.io.*;
import java.net.*;

/*
 * /*
服务端
那么为了可以让多个客户端同时并发访问服务端。
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。

如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。
*/
public class TCPserver {
    public static void main (String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(8888); 
        while(true){
            Socket s = ss.accept();
            //启动新线程
            new Thread(new PicThrowd(s)).start();
        }
    }

}

class PicThrowd implements Runnable{
    private Socket s;

    public PicThrowd(Socket s) {
        super();
        this.s = s;
    }

    public void run(){
        String ip = s.getInetAddress().getHostAddress();
        int count = 1;
        try{
            System.out.println(ip+"......connected");
            InputStream Inc = s.getInputStream();
            File dir = new File("d:\\pic");
            File file = new File(dir,ip+"("+count+")"+".jpg");
            FileOutputStream outc = new FileOutputStream(file);
            byte[] buf = new byte[2014];
            int len = 0;
            while((len=Inc.read(buf))!=-1){
                outc.write(buf,0,len);
            }
            OutputStream out = s.getOutputStream();
            out.write("上传成功".getBytes());
            Inc.close();
            outc.close();
            s.close();
        }catch(Exception e){
            throw new RuntimeException(ip+"上传失败");
        }
    }
}


/*
客户端。
1,服务端点。
2,读取客户端已有的图片数据。
3,通过socket 输出流将数据发给服务端。
4,读取服务端反馈信息。
5,关闭。
 */
class TCPclient{
    public static void main(String[] args) throws Exception{
        //对上传的图片首先进行判断
        if(args.length!=1)
        {
            System.out.println("请选择一个jpg格式的图片");
            return ;
        }
        File file = new File(args[0]);
        if(!(file.exists() && file.isFile()))
        {
            System.out.println("该文件有问题,要么补存在,要么不是文件");
            return ;
        }
        if(!file.getName().endsWith(".jpg"))
        {
            System.out.println("图片格式错误,请重新选择");
            return ;
        }

        if(file.length()>1024*1024*5)
        {
            System.out.println("文件过大,没安好心");
            return ;
        }       
        Socket s = new Socket("127.0.0.1",8888);
        FileInputStream fIn = new FileInputStream(file);
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[2014];
        int line = 0;
        while((line = fIn.read(buf))!=-1){
            out.write(buf, 0, line);
        }
        //告诉服务器已经写完了
        s.shutdownInput();
        //接受服务器发送的信息
        InputStream Inp = s.getInputStream();
        byte[] bufin = new byte[2014];
        int sum = Inp.read(bufin);
        System.out.println(new String(bufin,0,sum));
        fIn.close();
        s.close();
    }
}

例子3:TCP客户端并发登陆

package cn.dhj;
/*
客户端通过键盘录入用户名。
服务端对这个用户名进行校验。

如果该用户存在,在服务端显示xxx,已登陆。
并在客户端显示 xxx,欢迎光临。

如果该用户存在,在服务端显示xxx,尝试登陆。
并在客户端显示 xxx,该用户不存在。

最多就登录三次。
*/
import java.io.*;
import java.net.*;
//客户端
public class UerserLoderClient{
    public static void main (String[] args) throws Exception{
        Socket s = new Socket("127.0.0.1",8888);
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        BufferedReader bout = new BufferedReader(new InputStreamReader(s.getInputStream()));

        for (int i=1;i<=3;i++){
            String line = bufr.readLine();
            if (line == null)
                break;
            out.write(line);
            String info = bout.readLine();
            System.out.println("info"+info);
            if(info.contains("欢迎"))
                break;
        }
    }
}
//服务端
class UererLoaderServer{
    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(8888);   
        while(true){
            Socket s = ss.accept();
            new Thread(new ThreadServer(s)).start();
        }
    }
}
//利用多线程实现并发登录  
class ThreadServer implements Runnable{
    private Socket s;
    public ThreadServer(Socket s) {
        super();
        this.s = s;
    }
    public void run(){
        String ip = s.getInetAddress().getHostAddress(); 
        System.out.println(ip+"....connected");
        try{
            for(int i=1;i<=3;i++){
            BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String name = bufIn.readLine();
            if(name==null)
                break;
            BufferedReader bufr = new BufferedReader(new FileReader("user.text"));
            PrintWriter out = new PrintWriter(s.getOutputStream());
            String line = null;
            boolean flag = false;
            while((line=bufr.readLine())!=null){
                if(line.equals(name)){
                    flag = true;
                    break;
                }

            }
            if(flag = true){
                System.out.println(name+"已登入");
                out.write(name+"欢迎登入");
            }else{
                System.out.println(name+"尝试登入");
                out.write(name+"用户名不存在");
            }
            s.close();

            }
            }catch(Exception e){
                throw new RuntimeException(ip+"校验失败");
            }   
        }

}

例子4、客户端和游览器的演示
总结:游览器是一个客户端
java编译是在传输层和网际层处理的,会接受到全部的消息,包含了头消息。而浏览器处于应用层,已将发送来的头消息去除,只留下了主体信息。

import java.io.*;  
import java.net.*;  

//服务器  
class  ServerDemo  
{  
    public static void main(String[] args)throws Exception   
    {  
        //创建服务,监听端口  
        ServerSocket ss=new ServerSocket(10000);  
        //获取客户端  
        Socket s=ss.accept();  
        //显示ip  
        String ip=s.getInetAddress().getHostAddress();  

        System.out.println(ip);  
        //读取客户端读取流数据  
        InputStream in=s.getInputStream();  

        byte[] buf=new byte[1024];  
        int len=in.read(buf);  
        //显示数据  
        System.out.println(new String(buf,0,len));  
        //返回信息写入客户端输出流  
        PrintWriter out=new PrintWriter(s.getOutputStream(),true);///true一定要记得写  

        out.println("客户端你好!");  

        s.close();//关流  
        ss.close();  
    }  
}  

例子5、
自定义浏览器,显示网页信息

/* 
自定义浏览器,显示网页信息 
*/  

import java.io.*;  
import java.awt.*;  
import java.awt.event.*;  
import java.net.*;  

class MyIEGUIDemo  
{  
    //定义所需组件引用  
    private Frame f;  
    private Button but,bok;  
    private TextField tf;  
    private TextArea ta;  

    //构造函数  
    MyIEGUIDemo()  
    {  
        init();  
    }  

    //窗体基本设置于功能实现  
    public void init()  
    {  
        //组件实例化  
        f=new Frame("我的Window");  
        but=new Button("跳转");  
        tf=new TextField(50);  
        ta=new TextArea(25,60);  

        //基本设置  
        f.setBounds(300,150,500,500);  
        f.setLayout(new FlowLayout());  

        //添加组件  
        f.add(tf);  
        f.add(but);  
        f.add(ta);  

        //窗体事件  
        myEvent();  

        //窗体显示  
        f.setVisible(true);  
    }  

    //注册事件  
    public void myEvent()  
    {  
        //窗体关闭功能  
        f.addWindowListener(new WindowAdapter()  
        {  
            public void windowClosing(WindowEvent e)  
            {  
                System.exit(0);  
            }  
        });  

        //“跳转”按钮事件  
        but.addActionListener(new ActionListener()  
        {  
            public void actionPerformed(ActionEvent e)  
            {  
                showFile();//显示网页内容在文本区中  
            }  
        });  



        //文本框键盘事件  
        tf.addKeyListener(new KeyAdapter()  
        {  
            public void keyPressed(KeyEvent e)  
            {  
                //如果键盘按下Enter键,就将网页内容显示在文本区中  
                if(e.getKeyCode()==KeyEvent.VK_ENTER)  
                    showFile();  
            }  
        });  
    }  

    //显示网页内容  
        private void showFile()  
        {  
            ta.setText("");  
            String path=tf.getText();//获取输入的路径  
            try  
            {  
                //封装地址对象  
URL url =new URL(path);  
连接网页服务器  
                URLConnection conn=url.openConnection();  
                //读取流,用于读取服务器返回数据  
                InputStream in=conn.getInputStream();  

                byte[] buf=new byte[1024*1024];  

                int len=in.read(buf);  
                //将数据显示在文本区中  
                ta.append(new String(buf,0,len));  
            }  
            catch (Exception e)  
            {  
                throw new RuntimeException("连接"+path+"网站失败");  
            }  
        }  

    public static void main(String[] args)   
    {  
        //运行窗体  
        new MyIEGUIDemo();  
    }  
}  

自定义游览器知识储备和总结:
了解URL和URLConnection:
1、URL:
URI:范围更大,条形码也包含于此范围
URL:范围较小,即域名
方法:
1)构造函数:URL(String protocol,String host,int port,String file);//根据指定 protocol、host、port号和 file 创建 URL对象。
2)String getProtocol();//获取协议名称
3)String getHost();//获取主机名
4)int getPort();//获取端口号
5)String getFile();//获取URL文件名
6)String getPath();//获取此URL的路径部分
7)String getQuery();//获取此URL的查询部,客户端传输的特定
2、URLConnection
方法:
1)URLConnection openConnection();//用URL调用此方法,返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
2)InputStream getInputStream();//获取输入流
3)OutputStream getOutputStream();//获取输出流

你可能感兴趣的:(黑马程序员技术博客)