网络编程2

1、实现客户端上传图片
问题分析客户端

a、服务端点。
b、读取客户端已有的图片数据
c、通过Socket输出流将数据发给服务端
d、读取服务端反馈信息。
e、关闭

问题分析服务端

a、服务端服务,并监听窗口
b、获取客户端对象,并获取客户ip
c、读取客户端输入流数据
d、写入文件
e、用客户端输出流反馈信息
f、关流
packageorg.nagi.net;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.net.ServerSocket;
importjava.net.Socket;
/**
 *图片上传的服务器端
 *@author dell
 *
 */
publicclass PictureServer {
   publicstaticvoid main(String[] args) {
      try {
        //建立一个服务器在12345端口监听
        ServerSocket server = new ServerSocket(12345);
        //连接客户端
        Socket s =server.accept();
        //得到输入流
        InputStream in = s.getInputStream();
        FileOutputStream out = new FileOutputStream("btbu.png");
        int i = -1;
        byte bs[] =newbyte[1024];
        while((in.read(bs) != -1)){
          out.write(bs, 0, i);
        }
        //得到输出流向客户端发送数据告诉已经上传成功
        OutputStream sout = s.getOutputStream();
        sout.write(("upload success !").getBytes());
        sout.close();
        in.close();
        s.close();
        server.close();
      } catch (IOException e) {
        e.printStackTrace();
      } 
   }
}

packageorg.nagi.net;

importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.OutputStream;
importjava.net.Socket;
importjava.net.UnknownHostException;
/**
 *图片上传的客户端
 *@author dell
 *
 */
publicclass PictureClient {
   publicstaticvoid main(String[] args) {
      try {
        //连接服务器 12345端口
        Socket s = new Socket("127.0.0.1",12345);
        //得到输出流
        OutputStream out = s.getOutputStream();
        FileInputStream fis = new FileInputStream("1.gif");
        byte[] bs =newbyte[1024];
        int line = -1;
        while((line=fis.read(bs)) != -1){
          out.write(bs, 0, line);
        }
        //告诉服务器已经发送完成
        s.shutdownOutput();
        out.close();
        s.close();
      } catch (UnknownHostException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      } 
   }
}

但是以上的出现一个问题——图片的上传只是一对一上传的,不能够多人上传;这个我们就需要解决多人上传图片的问题。
原因分析:服务器段存在有着局限性,当A客户端的连接到之后,被服务器端获得到,服务器就会执行相应的流程,这时客户端B连接上来只能在等待。原因是服务器在处理客户端A的请求的时候,在while循环一直是处于一个堵塞状态,没有机会处理客户端B的数据请求。

解决思想:为了使得每一个用户都可以并发的访问服务器,我们将每一个用户的请求都封装在一个线程里面。这样可以同时处理多个用户的请求。

例子代码:

packageorg.nagi.base;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.net.ServerSocket;
importjava.net.Socket;
/**
 *并发的处理多个用户提交上来的图片
 */
class PictureServer
{
   publicstaticvoid main(String[] args)throws Exception
   {
      //创建服务,监听端口
      @SuppressWarnings("resource")
      ServerSocket ss=new ServerSocket(12345);

      while (true)
      {
        //获取客户端对象
        Socket s=ss.accept();
        //只要出现一个客户一个新的线程立即执行
        new Thread(new PicThread(s)).start();
      }

   }
}

//利用多线程实现并发上传
class PicThreadimplements Runnable{
   private Sockets;
   PicThread(Socket s){
      this.s=s;
   }
   //复写Run的方法
   publicvoid run()
   {
      //图片计数器保证提交的图片不会被覆盖
      int count=1;
      //获取客户端ip
      String ip=s.getInetAddress().getHostAddress();
      try
      {    
        //通过客户端的读取流读取数据
        InputStream in=s.getInputStream();
        //文件保存路径
        File dir =new File("C:\\picture\\a.jpg");
        //文件名
        File file=new File(dir,ip+".jpg");
        //判断文件是否存在
        while(file.exists()){
          file=new File(dir,ip+"("+(count++)+").jpg");
        }
        //将数据写入到指定文件中
        FileOutputStream fos=new FileOutputStream(file);

        byte[] buf=newbyte[1024];
        int len=0;
        while ((len=in.read(buf))!=-1)
        {
          //向外写数据
          fos.write(buf,0,len);
        }

        //将收到图片数据的信息返回给客户端
        OutputStream out=s.getOutputStream();
        out.write("上传成功!".getBytes());
        fos.close();//关流
        s.close();//关闭socket流
      }
      catch (Exception e)
      {
        //如果出现错误的话,就会打印出错误
        e.printStackTrace();
      }
   }
}

客户端代码:

import java.io.*;
import java.net.*;
/**
 * 客户端
 * @author dell
 *
 */
class PictureClient
{
   public staticvoid main(String[] args) {
      try{
      //对传入的值进行判断
      if(args.length!=1)
      {
        System.out.println("请选择上传一个图片文件!");
        return;
      }

      File file=newFile(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*4)
      {
        System.out.println("你上传的文件过大!");
        return;
      }

      //创建服务监听在本机12345端口上
      Socket s=newSocket("127.0.0.1",12345);
      //读取图片数据
      FileInputStream fis=newFileInputStream(file);

      //用Socket服务输出流写入数据
      OutputStream out =s.getOutputStream();

      //封装读取流
      BufferedReader in=new BufferedReader(newInputStreamReader(s.getInputStream()));

      byte[] buf=new byte[1024];

      int len=0;

      while ((len=fis.read(buf))!=-1)
      {
        out.write(buf,0,len);
      }

      //结束标记,表示文件数据已经上传完了告诉服务器已经上传完成
      s.shutdownOutput();

      String info=in.readLine();//读取返回信息
      System.out.println(info);

      fis.close();//关流
      s.close();//关闭socket

      }catch (Exception e){
        //如果出现了错误的话,打印出错误
        e.printStackTrace();
      }
   }
}

2、客户并发的登陆

需求:实现客户端通过键盘录入用户名,服务端对这个用户名进行校验。
如果该用户存在,在服务端显示xxx,已登陆;并在客户端显示xxx:欢迎光临。
如果用户不存在,在服务端显示xxx,尝试登陆;并在客户端显示xxx:该用户不存在。
最多就登录三次。

问题分析:用户存在打印出用户信息,如果不存在则打印出尝试登陆
解决方案:首页、服务器端可以并发的接收的客户端提交的信息,得到客户端信息之后,将得到的信息和用户信息表进行逐一比较,如果匹配成功之后,打印出用户信息;如果比配不成的话,服务端显示xxx,尝试登陆 ,向客户端打印,该用户不存在。
代码:

packageorg.nagi.net;

importjava.io.BufferedReader;
importjava.io.FileReader;
importjava.io.InputStreamReader;
importjava.io.PrintWriter;
importjava.net.ServerSocket;
importjava.net.Socket;

/**
 *客户登陆服务器端
 *@author dell
 *
 */
classUserLoginServer{
   publicstaticvoid main(String [] args){
      //创建服务,监听端口
      try{
      ServerSocket ss=new ServerSocket(12345);

      while (true)
      {
        //获取客户端对象
        Socket s=ss.accept();

        //客户端执行线程
        new Thread(new LoginThread(s)).start();
      }

      }catch(Exception e){
        e.printStackTrace();
      }
   }
}

/**
 *利用多线程实现并发登录
 *@author dell
 *
 */
class LoginThreadimplements Runnable{
   private Sockets;
   LoginThread(Socket s){
      this.s=s;
   }
   publicvoid run(){
      //获取客户端ip
      String ip=s.getInetAddress().getHostAddress();
      System.err.println("客户端用户:" + ip);//打印用户信息
      try
      {    
        for (int i=0;i<3 ;i++ )
        { 
          //通过客户端的读取流读取数据
          BufferedReader in =
                new BufferedReader(new InputStreamReader(s.getInputStream()));

          //读取数据库中的数据,这里用文件来表示数据库
          BufferedReader br=new BufferedReader(new FileReader("users.txt"));

          String line=in.readLine();//读取客户端数据
          if (line==null){//如果没有数据的话放回为空 读一行校验一行
             break;//如果客户端没有发送数据,则跳出循环
          }
          String data=null;
          boolean flag=false;//设置标记
          //读取数据库中的用户数据
          while ((data=br.readLine())!=null)
          {
             if (line.equals(data)){
                flag=true;//如果用户存在,则将标记设为true
                break;
             }
          }

          //将数据写入到指定文件中
          PrintWriter out=new PrintWriter(s.getOutputStream(),true);

          if (flag)//如果用户存在的话,打印出用户信息
          {
             System.out.println(line+",已登陆!");

             out.println(line+":欢迎光临!");

             break;
          }
          else
          {
             System.out.println(line+",尝试登陆!");
             out.println(line+":用户名不存在!");
          } 
        }
        s.close();//关流
      }
      catch (Exception e)
      {
        //出现错误。并且打印
        e.printStackTrace();
      } 
   }
}
package org.nagi.net;
import java.io.*;
import java.net.*;
/**
 *用户登陆客户端
 *@author dell
 *
 */
class UserLoginClient{
   publicstaticvoidmain(String[] args) throws Exception
   {
      //在本地建立一个端口为12345服务器,
      Socket s=new Socket("127.0.0.1",12345);
      //从键盘得到标准的输出流
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

      //用Socket服务输出流写入数据 true:表示是PrintWriter自动flush()
      PrintWriter out =new PrintWriter(s.getOutputStream(),true );

      //接收服务器返回的信息
      BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));

      String line=null;

      for(int i=0;i<3;i++)
      {
        line=br.readLine();//读取键盘录入
        if (line==null)//输入端可能出现为空,保证没有空格键
        {
          break;//如果键盘没有输入,则直接结束
        }
        out.println(line);//将数据写入流中
        String info=in.readLine();//读取返回信息
        System.out.println(info);
        if (info.contains("欢迎"))       {
          break;//如果登录成功,就跳出循环
        }
      }

      br.close();//关流
      s.close();//关闭socket
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值