//需求:多个用户同时上传图片到服务端。
import java.io.*;
import java.net.*;
/*
客户端。
1,服务端点。
2,读取客户端已有的图片数据。
3,通过socket 输出流将数据发给服务端。
4,读取服务端反馈信息。
5,关闭。
*/
class PicClient
{
public static void main(String[] args)throws Exception //用到了主函数的args参数,在dos运行时直接写:java UploadPicByThread c:\1.jpg
{
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"))//规定格式是jpg
{
System.out.println("图片格式错误,请重新选择");
return ;
}
if(file.length()>1024*1024*5)//规定文件大小
{
System.out.println("文件过大");
return ;
}
Socket s = new Socket("192.168.1.254",10007);//指定发送地点
FileInputStream fis = new FileInputStream(file);//本地文件读取流
OutputStream out = s.getOutputStream();//网络输出流
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1)
{
out.write(buf,0,len);
}
s.shutdownOutput();//告诉服务端数据已写完
InputStream in = s.getInputStream();//网络读取流,获取服务端的反馈信息
byte[] bufIn = new byte[1024];
int num = in.read(bufIn);
System.out.println(new String(bufIn,0,num));
fis.close();//关闭资源
s.close();
}
}
/*
服务端
为了可以让多个客户端同时并发访问服务端。
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求。
如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码即可,将该代码存入run方法中。
*/
class PicServer
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10007);//服务端监听指定端口
while(true)
{
Socket s = ss.accept();
new Thread(new PicThread(s)).start();//每进来一个客户就启动一个线程,一旦启动就可以下一个循环,就能获取别的客户
}
//ss.close();//不用关,服务器要一直开着
}
}
class PicThread implements Runnable//线程。其实是服务端要做的动作,对连接过来的每个客户都开启一个线程
{
private Socket s;
PicThread(Socket s)//一new线程就带有客户端
{
this.s = s;
}
public void run()
{
int count = 1;//计数器,同个客户每次上传的文件所存的名字要区分1234....
String ip = s.getInetAddress().getHostAddress();//获取此客户ip
try
{
System.out.println(ip+"....connected");//显示这个客户已连上
InputStream in = s.getInputStream();//获取输入流
File dir = new File("d:\\pic");//要存的路径
File file = new File(dir,ip+"("+(count)+")"+".jpg");//要存的路径和文件名,文件名含计数器
while(file.exists())//已编过号的文件不能重名,就把计数器一直增大,知道没有重名
file = new File(dir,ip+"("+(count++)+")"+".jpg");
FileOutputStream fos = new FileOutputStream(file);//输出到指定路径指定文件
byte[] buf = new byte[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();
}
catch (Exception e)
{
throw new RuntimeException(ip+"上传失败");
}
}
}