• Java:网络编程之应用实例


    1、聊天
    编写一个聊天程序,有收数据的部分和发数据的部分。
    这两部分需要同时执行,那么就需要多线程技术。
    一个线程控制发送。
    一个线程控制接收。
    因为收和发动作是不一致的,所以要定义两个run方法,而且分别封装到不同的类中。
    //例子如下:
    import java.net.*;
    import java.io.*;
    //发送端
    class ChatSend implements Runnable
    {
        private DatagramSocket ds;
        public ChatSend(DatagramSocket ds)
        {
            this.ds = ds;
        }
        public void run()
        {
            try
            {
                BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
                String line = null;
                while((line=bufr.readLine())!=null)
                {
                    if("quit".equals(line))
                        break;
                    byte[] buf = line.getBytes();
                    DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10000);
                    ds.send(dp);
                }
            }
            catch(Exception e)
            {
                throw new RuntimeException("发送数据失败!");
            }
        }
    }
    //接收端
    class ChatRece implements Runnable
    {   
        private DatagramSocket ds;
        public ChatRece(DatagramSocket ds)
        {
            this.ds = ds;
        }
        public void run()
        {
            try
            {
                  while(true)
                {
                    byte[] buf = new byte[1024];
                    DatagramPacket dp = new DatagramPacket(buf,buf.length);
                    ds.receive(dp);
                    String IP = dp.getAddress().getHostAddress();
                    //int port = dp.getPort();
                    String message = new String(dp.getData(),0,dp.getLength());
                    System.out.println("IP:"+IP+"  "+"message:"+message);
                }
            }
            catch(Exception e)
            {
                throw new RuntimeException("接收数据失败!");
            }
        }
    }
    //测试类
    class ChatDemo
    {
        public static void main(String[] args)throws Exception
        {
            DatagramSocket sendscoket = new DatagramSocket();
            DatagramSocket recescoket = new DatagramSocket(10000);
            
            new Thread(new ChatSend(sendscoket)).start();
            new Thread(new ChatRece(recescoket)).start();
        }
    }

    2、使用TCP协议复制文件

    //例子如下:
    import java.io.*;
    import java.net.*;
    class TextClient
    {
        public static void main(String[] args)throws Exception
        {
            Socket s = new Socket("192.168.1.105",10002);
            //读取文件流
            BufferedReader bufr = new BufferedReader(new FileReader("TextCopyDemo.java"));
            
            //客户端输出流的目的
            PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//自动刷新和换行
            
            String line = null;
            while((line=bufr.readLine())!=null)
            {
                pw.println(line);
            }
            
            s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1 
            //pw.println("over");
            
            //客服端读取流的源
            BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String str = bufin.readLine();
            System.out.println(str);
            
            bufr.close();
            s.close();
        }
    }
    
    class TextServer
    {
        public static void main(String[] args)throws Exception
        {
            ServerSocket ss = new ServerSocket(10002);
            
            Socket s = ss.accept();
            String IP = s.getInetAddress().getHostAddress(); 
            System.out.println("server:"+IP);
            
            
            //服务端读取流的源
            BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
            
            //输出文件流
            PrintWriter pw = new PrintWriter(new FileWriter("F:\myfile\TcpText.txt"),true);//自动刷新和换行
               
            String line = null;
            while((line=bufin.readLine())!=null)
            {
                //if("over".equals(line))
                    //break;
                pw.println(line);
            }
            
            //服务端输出流的目的
            PrintWriter ps = new PrintWriter(s.getOutputStream(),true);
            ps.println("文件复制成功!");
            
            pw.close();
            s.close();
            ss.close();
        }
    }
    3、需求:建立一个文本转换服务器。
    客户端给服务端发送文本,服务端会将文本转换成大写再返回给服务端,
    而且服端可以不断的进行大写转换,直到遇到over时,转换结束。
    分析:
    客服端:既然是操作设备上数据,那么就可以使用io技术,并按照io的操作来思考。
    源:键盘录入
    目的:网络设备,即网络输出流。
    而且操作的是文本数据,可以选择字符流。
     
    步骤:1.建立服务
             2.获取键盘录入
             3.将数据发给服务端
             4.获取服务端返回的大写数据
              5.结束,关闭资源 
     都是文本数据,可以使用字符流进行操作,同时提高效率,可以使用缓冲。
    //例子如下:
    import java.io.*;
    import java.net.*;
    
    class TransTcpClinet
    {
        public static void main(String[] args)throws Exception
        {
            //创建客户端的Socket服务,指定目的主机和端口
            Socket s = new Socket("192.168.1.105",10000);
            
            //定义读取键盘录入的流对象
            BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
            
            //定义目的,将数据写入socket的输出流,发给服务端
            //BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            PrintWriter pw = 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;    
                
                pw.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 TransTcpServer
    {
        public static void main(String[] args)throws Exception
        {
            //建立服务端的SocketServer服务,并监听一个端口
            ServerSocket ss = new ServerSocket(10000);
            
            //通过accept方法获取连接过来的客服端对象
            Socket s = ss.accept();
            String IP = s.getInetAddress().getHostAddress();
            System.out.println(IP+"...connected!");    
            
            
            //源。读取Scoket读取流中的数据
            BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));
            
            //目的。Scoket输出流将大写的数据写入到Scoket输出流,并发送给客服端。
            //BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//带自动刷新和换行
            
            String line = null;
            while((line=bufin.readLine())!=null)
            {
                pw.println(line.toUpperCase());
                
                System.out.println(line);
                //bufout.write(line.toUpperCase());
                //bufout.newLine();
                //bufout.flush();
            }
            s.close();
            ss.close();
        }
    }
    
    /*
    该例子出现的问题:
    现象:客服端和服务端都在莫名的等待。
    为什么呢?
    因为客服端和服务端都有阻塞式方法,这些方法没有读取到结束标志,就导致两边一直等待。
    */
    4、需求:单线程上传图片
    import java.io.*;
    import java.net.*;
    客服端:
    (1).服务端点
    (2).读取客服端已有的图片数据
    (3).通过socket输出流将图片发给服务端
    (4).读取服务端反馈信息
    (5).关闭。
    //例子如下:
    //客户端
    class
    PicClient { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.105",10000); //图片读取流的源 FileInputStream fis = new FileInputStream("F:\myfile\1.jpg"); //socket输出流的目的 PrintStream ps = new PrintStream(s.getOutputStream(),true); byte[] buf = new byte[1024]; int num = 0; while((num=fis.read(buf))!=-1) { ps.write(buf,0,num); } s.shutdownOutput();//关闭客户端的输出流,告诉服务端数据已经写完,相当于给流中加入一个结束标记-1 //socket读取流的源(读取反馈信息) InputStream in = s.getInputStream(); byte[] bufin = new byte[1024]; int len = in.read(bufin); System.out.println(new String(bufin,0,len)); fis.close(); s.close(); } }
    /* 服务端: 1.服务端点 2.用服务端读取流读取客服端输出流发送过来的图片数据 3.用文件写入流将图片写入指定文件夹 4.服务端输出流发送反馈信息给客服端 5.关闭。 */
    class PicServer { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10000); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"......connected!"); //图片输出流的目的 FileOutputStream fos = new FileOutputStream("F:\myfile\server.jpg"); //SocketServer读取流的源 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf))!=-1) { fos.write(buf,0,len); } //SocketServer输出流的目的(输出反馈信息) PrintStream ps = new PrintStream(s.getOutputStream(),true); ps.write("图片上传成功!".getBytes()); fos.close(); s.close(); ss.close(); } }
    5、需求:多线程上传图片
    import java.io.*;
    import java.net.*;
    客服端:
    (1).服务端点
    (2).读取客服端已有的图片数据
    (3).通过socket输出流将图片发给服务端
    (4).读取服务端反馈信息
    (5).关闭。
    //例子如下:
    //客户端
    class
    PicClient { public static void main(String[] args)throws Exception { if(args.length!=1) { System.out.println("请选择一个jpg类型的图片"); return ; } File file = new File(args[0]);//"F:\myfile\1.jpg" 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("192.168.1.105",10000); //图片读取流的源 FileInputStream fis = new FileInputStream(file); //socket输出流的目的 PrintStream ps = new PrintStream(s.getOutputStream(),true); byte[] buf = new byte[1024]; int num = 0; while((num=fis.read(buf))!=-1) { ps.write(buf,0,num); } s.shutdownOutput();//关闭客户端的输出流,告诉服务端数据已经写完,相当于给流中加入一个结束标记-1 //socket读取流的源(读取反馈信息) InputStream in = s.getInputStream(); byte[] bufin = new byte[1024]; int len = in.read(bufin); System.out.println(new String(bufin,0,len)); fis.close(); s.close(); } } /* 服务端: 这个服务端有个局限性,当A客服端连上以后,被服务端收到。服务端执行具体流程。 这时,B客服端连接只有等待。因为服务端还没有处理完A客服端的请求,还没有循环 回来执行accept方法。所以,暂时获取不到B客户端对象。那么,为了能让多个客服端并发 访问服务端,服务端最好就是将每个客服端封装到一个单独的线程中,这样,可以同时处理 多个客服端的请求。 如何定义线程呢? 只要明确了每一个客户端要在服务端执行的代码即可,将该代码存入到run方法中。 */ class PicThread implements Runnable { private Socket s; PicThread(Socket s) { this.s = s; } public void run() { int count=1; String ip = s.getInetAddress().getHostAddress(); try { System.out.println(ip+"......connected!"); //图片输出流的目的 File file = new File(ip+"("+count+")"+".jpg"); while(file.exists()) file = new File(ip+"("+(count++)+")"+".jpg"); FileOutputStream fos = new FileOutputStream(file); //SocketServer读取流的源 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = 0; while((len=in.read(buf))!=-1) { fos.write(buf,0,len); } //SocketServer输出流的目的(输出反馈信息) PrintStream ps = new PrintStream(s.getOutputStream(),true); ps.write("图片上传成功!".getBytes()); fos.close(); s.close(); } catch(Exception e) { throw new RuntimeException(ip+"上传失败!"); } } }
    //测试类
    class PicServer { public static void main(String[] args)throws Exception { ServerSocket ss = new ServerSocket(10000); while(true) { Socket s = ss.accept(); new Thread(new PicThread(s)).start(); } //ss.close(); } }
  • 相关阅读:
    一个人事工资模块
    Delete From 带 inner join
    打开SQL AnyWhere *.db数据库
    开启查询IO操作统计
    一个大数据量表访问优化联动下拉框查询优化
    一个简单的配置文件读取类
    MSSQL2005 双机热备说明
    数据库镜像
    GridView + ObjectDatasource 的一个范例代码
    往带自增长列的数据表中导数据
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4918936.html
Copyright © 2020-2023  润新知