黑马程序员_java基础day24

------- android培训java培训、期待与您交流! ----------

主要内容:一、TCP上传图片;二、TCP-客户端并发登录;三、URL:统一资源定位符;四、小知识点。
一、TCP上传图片

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

import java.io.*;
import java.net.*;
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]);//主函数传值,传路径
		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.101",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();
	}
}

/*
服务端:


这个服务端有个局限性,当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");

			InputStream in = s.getInputStream();

			File file = new File(ip+"("+(count)+")"+".jpg");//192.168.1.101(1).jpg

			while(file.exists())
				file = new File(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+"上传失败");
		}
	}
}
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();
	}
}

二、TCP-客户端并发登录
客户端通过键盘录入用户名。
服务端对这个用户名进行校验。


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


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


最多就登录三次。

import java.io.*;
import java.net.*;
class  LoginClient
{
	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("192.168.1.101",10008);

		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));

		PrintWriter out = new PrintWriter(s.getOutputStream(),true);

		BufferedReader bufIn =
			new BufferedReader(new InputStreamReader(s.getInputStream()));

		for(int x=0;x<3;x++)
		{
			String line = bufr.readLine();
			if(line==null)
				break;
			out.println(line);

			String info = bufIn.readLine();
			System.out.println("info:"+info);
			if(info.contains("欢迎"))
				break;
		}
		bufr.close();
		s.close();
	}
}

class UserThread implements Runnable
{
	private Socket s;
	UserThread(Socket s)
	{
		this.s = s;
	}
	public void run()
	{
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"....connected");
		try
		{
			for(int x=0;x<3;x++)
			{
				BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

				String name = bufIn.readLine();
				if(name==null)
					break;

				BufferedReader bufr = new BufferedReader(new FileReader("User.txt"));

				PrintWriter out = new PrintWriter(s.getOutputStream(),true);

				String line = null;

				boolean flag = false;
				while((line=bufr.readLine())!=null)
				{
					if(line.equals(name))
					{
						flag = true;
						break;
					}
				}
				if(flag)
				{
					System.out.println(name+",已登录");
					out.println(name+",欢迎光临");
					break;
				}
				else 
				{
					System.out.println(name+",尝试登录");
					out.println(name+",用户名不存在");
				}
			}
			s.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException(ip+"校验失败");
		}
	}
}
class  LoginServer 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss = new ServerSocket(10008);

		while(true)
		{
			Socket s = ss.accept();

			new Thread(new UserThread(s)).start();
		}
	}
}

三、URL:统一资源定位符,它是指向互联网“资源”的指针。
资源可以是简单的文件或者目录,也可以是对更为复杂的对象的引用。




String getFile() 
 获取此 URL 的文件名。
String getHost() 
 获取此 URL 的主机名(如果适用)。
String getPath() 
 获取此 URL 的路径部分。
int getPort() 
 获取此 URL 的端口号。
String getProtocol() 
 获取此 URL 的协议名称。
String getQuery() 
 获取此 URL 的查询部分。


例一:

import java.net.*;
class URLDemo 
{
	public static void main(String[] args) throws MalformedURLException
	{
		URL url = new URL("http://192.168.1.101/myweb/demo.html?name=haha&age=30");

		System.out.println("getProtocol():"+url.getProtocol());
		System.out.println("getHost():"+url.getHost());
		System.out.println("getPort():"+url.getPort());
		System.out.println("getPath():"+url.getPath());
		System.out.println("getFile():"+url.getFile());
		System.out.println("getQuery():"+url.getQuery());

		/*
		int port = getPort();
		if(port==-1)
			port = 80;
		*/
	}
}

例二:

import java.net.*;
import java.io.*;
class  URLConnectionDemo
{
	public static void main(String[] args) throws Exception
	{
		URL url = new URL("http://www.sina.com.cn");

		URLConnection conn = url.openConnection();

		System.out.println(conn);

		InputStream in = conn.getInputStream();

		byte[] buf = new byte[1024];

		int len = in.read(buf);

		System.out.println(new String(buf,0,len));
	}
}

四、需要注意和掌握的几个小知识点
    1,在创建Socket()时,有一个不需要传递主机和端口的空参数构造函数。
        它会用一个  void connect(SocketAddress endpoint)方法去连接。
        SocketAddress 与InetAddress 的区别:
        InetAddress封装的是:IP地址。
SocketAddress是一个抽象类,它的子类InetSocketAddress封装的是:(IP 地址 + 端口号)。


    2,ServerSocket(int port, int backlog);port是监听窗口,backlog是同时指定队列的最大长度。
        队列的最大长度:指的是客户端同时能连接到服务器的最大个数。


InetAddress.getByName("www.sina.com.cn");获取新浪的ip地址。    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值