黑马程序员——Java基础:网络编程

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

 

一、网络编程

网络编程:在java.net包中。

网络通信

      1.首先要找到对方的IP。

      2.数据要发送到对方指定的应用程序上,为了标识这些程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这个数字,我们叫做端口,逻辑端口(0~65535,其中0~1024被系统用了,或成为保留端口)。

      3.定义网络规则,这个网络规则称为协议。国际组织定义了通用协议TCP/IP。

网络通信的三要素是:IP地址,端口号,传输协议。

注:可在dos中输入:ping 127.0.0.1或ping localhost(称为:本地回环地址)来测试网卡。

        在dos中输入:ipconfig可查看本机地址。

网络参考模型:

注:通常用户操作的是应用层,而编程人员需要做的是传输层和网际层,用户在应用层操作的数据,经过逐层封包,最后到物理层发送到另一个模型中,再进行逐层解包

那么如何获取IP地址呢?

示例:获取IP

import java.net.*;
class TCPAddressDemo 
{
	public static void main(String[] args) throws UnknownHostException
	{
		//获取本机地址和名称
		InetAddress i=InetAddress.getLocalHost();
		String address=i.getHostAddress();
		String name=i.getHostName();
		//获取百度地址
		InetAddress ia=InetAddress.getByName("www.baidu.com");
		String str=ia.getHostAddress();
		System.out.println("address:"+address+"\tname:"+name);
		System.out.println("address:"+str);
	}
}

常见的传输协议

   1)UDP特点:

    1.面向无连接,即将数据及源和目的封装成数据包中,不建立链接的发送/面向无连接。

          2.每个数据包的大小限制在64K之内/数据会封包,限制在64K内。

          3.因无连接,是不可靠的协议/不可靠。

          4.不建立连接,速度快/速度快,易丢包。

    如:视频会议、聊天软件等。

   2)TCP特点:

          1.面向连接,在建立连接后,形成传输数据的通道/面向对象。

          2.在连接中进行大数据量的传输。

          3.通过三次握手完成连接,是可靠的协议。

          4.必须建立连接,效率稍慢。

    如:打电话,下载等。

注:三次握手第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。

       如:找人时,A:在? B:在。A:我知道了。

二、网络传输

1)UDP传输(DatagramSecket和DatagramPacket)的步骤:

        1.创建发送器,接收器。

        2.建立数据包。

        3.调用socket的发送接收方法。

        4.关闭socket。

注:发送端和接收端是两个独立运行的程序。

其中,socket:它被称之为插座,为网络服务提供的一种机制。相当于码头,想要通信先要有港口。通信的两端都要有socket。网络通信其实就是socket之间的通信。数据在两个socket之间通过IO传输。

示例:定义一个应用程序,用于接收UDP协议传输的数据并处理

/*需求:定义一个应用程序,用于接收UDP协议传输的数据并处理
思路:1.定义一个UDP的socket服务,通常会监听一个端口,就是给这个接收网络应用程序定一个数字标识,
方便明确哪些数据过来该应用程序可以进行处理
2.定义一个数据包,用来存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3.通过socket服务的receive方法接收到的数据存入已定义好的数据包中
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上
5.关闭资源*/
import java.net.*;
class UDPRece2308
{
	public static void main(String[] args)  throws Exception
	{
		 receUDP();
	}
	//接收数据
	public static void receUDP()throws Exception
	{
		DatagramSocket ds=new DatagramSocket(10000);//建立接收端
		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length);//创建包,用于存储数据
		ds.receive(dp);//调用socket服务的接收方法,将接收到的数据存到包中
		//获取包中的数据信息
		String ip=dp.getAddress().getHostAddress();
		String data=new String(dp.getData(),0,dp.getLength());
		int port=dp.getPort();
		System.out.println("ip="+ip+"data="+data+"port="+port);
		ds.close();//关闭资源
	}
}

先将程序打开,等待数据传过来

示例:通过UDP传输方式,将一段文字数据发送出去。

/*需求:通过UDP传输方式,将一段文字数据发送出去。
思路:1.建立UDP的socket服务
      2.提供数据,并将数据封装进包中
      3.通过socket服务的发送功能,将数据发送出去
      4.关闭资源
*/
import java.net.*;
class UDPSend2308
{
	public static void main(String[] args) throws Exception
	{
		 sendUDP();
	}
	//发送数据
	public static void sendUDP()throws Exception
	{
		DatagramSocket ds=new DatagramSocket();//建立发送端
		byte[] buf="Hello world".getBytes();
		//建立数据包
		DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.111"),10000);
		ds.send(dp);//调用socket服务的发送功能,将数据发送出去
		ds.close();//关闭资源
	}
}

传输数据:

UDPRece2308接收到的数据:

练习:编写一个聊天程序。如qq

/*编写一个聊天程序。如qq
有收数据部分,和发数据部分,这两部分同时执行,用到多线程

udp的发送端:
1:建立udp的socket服务,创建对象时如果没有明确端口,系统会自动分配一个未被使用的端口。
2:明确要发送的具体数据。
3:将数据封装成了数据包。
4:用socket服务的send方法将数据包发送出去。
5:关闭资源。

udp的接收端:
1:创建udp的socket服务,必须要明确一个端口,作用在于,只有发送到这个端口的数据才是这个接收端可以处理的数据。
2:定义数据包,用于存储接收到数据。
3:通过socket服务的接收方法将收到的数据存储到数据包中。
4:通过数据包的方法获取数据包中的具体数据内容,比如ip、端口、数据等等。
5:关闭资源。
*/
import java.io.*;
import java.net.*;
//发送
class Send implements Runnable
{
	private DatagramSocket ds;
	public Send(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("886".equals(line))
					break;
				byte[] buf=line.getBytes(); // 2,明确要发送的具体数据。
				DatagramPacket dp=new DatagramPacket(buf // 3,将数据封装成了数据包。
					,buf.length,InetAddress.getByName("192.168.139.1"),10010);
				ds.send(dp);// 4,用socket服务的send方法将数据包发送出去。
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("发送失败");
		}	
	}
}
//接收
class Rece implements Runnable
{
	private DatagramSocket ds;
	public Rece(DatagramSocket ds)
	{
		this.ds=ds;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				byte[] buf=new byte[1024];
				// 2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。
				DatagramPacket dp=new DatagramPacket(buf,buf.length);
				// 3,通过socket服务的接收方法将收到的数据存储到数据包中。
				ds.receive(dp);
				// 4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。
				String ip=dp.getAddress().getHostAddress();
				int port = dp.getPort();
				String data=new String(dp.getData(),0,dp.getLength());
				System.out.println(ip+"::"+"::"+port+"::"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收失败");
		}	
	}
}

class UDPDemo
{
	public static void main(String[] args) throws Exception
	{
		// 1,建立udp的socket服务。
		DatagramSocket send=new DatagramSocket();//端口可以不指定,系统会随机分配。
		// 1,创建udp的socket服务。
		DatagramSocket rece=new DatagramSocket(10010);
		new Thread(new Send(send)).start();
		new Thread(new Rece(rece)).start();
	}
}

2)TCP传输(Socket和ServerSocket)的步骤:

        1.创建客户端和服务器端

        2.建立连接后,通过socket中的IO流进行数据的传输

        3.关闭socket

注:同样客户端和服务器端是两个独立的应用程序。

服务端:

        服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。需监听一个端口。

         1)建立服务端的Socket服务,并监听一个端口。

         2)获取连接过来的客户对象,通过ServerSocket的accept()方法,没有连接就会等待,所以此方法是阻塞式的。

         3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。

         4)关闭服务端(可选)。一般服务端是常开的,因为在实际应用中,随时有客户端在请求连接和服务。但这里需要定时关闭客户端对象流,避免某一个客户端长时间占用服务器端。

注:ServerSocket(int port,int packlog):其中backlog表示队列的最大长度,即最多连入客户端的个数,即最大连接数。

示例:定义端点接收数据并打印在控制台上

import java.io.*;
import java.net.*;
class TCPServerDemo2309 
{
	public static void main(String[] args) throws IOException
	{
		//建立服务端的Socket服务,并监听一个端口
		ServerSocket ss=new ServerSocket(10001);
		//通过accept方法获取连接过来的客户端对象
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		//获取客户端发送过来的数据,通过客户端读取流的方式来读取数据
		InputStream in=s.getInputStream();
		byte[] buf=new byte[1024];
		int len=in.read(buf);
		String data=new String(buf,0,len);
		System.out.println("ip:"+ip+"\tdata:"+data);
		s.close();
		ss.close();
	}
}


打开服务端:

客户端:

     通过查阅Socket对象的API文档,发现在该对象在建立时,就可去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。

      1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取

      2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流

      3)通过输出流的write()方法将要发送的数据写入到流中

      4)关闭Socket流资源

注:创建Socket对象,可以创建空参数的Socket对象。如Socket s=new Socket();通过connect(SocketAddress endPoint)方法来连接到服务器。其中,SocketAddress 的子类InetSocketAddress 封装了ip地址和端口。

示例:给服务器发送一个文本数据

/*需求:给服务端发送一个文本文件
思路:创建socket服务,并指定要连接的主机和端口
*/
import java.io.*;
import java.net.*;
class  TCPClientDemo2309
{
	public static void main(String[] args) throws IOException
	{
		//创建客户端socket对象,指定目的主机和端口,对象一建立,流就建立了
		Socket s=new Socket("192.168.1.111",10001);
		//获取socket流中的输出流
		OutputStream out=s.getOutputStream();
		out.write("Hello World".getBytes());
		s.close();
	}
}

客户端发送数据:

服务端接收到的数据:

练习1:建立一个文本转换服务器。客户端TCPClient2313,服务端TCPServer2313。客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端,而客户端可以不断的进行文本转换,可客户端输入over时,转换结束。

服务端:

分析:
服务端:
	源:socket读取流
	目的:socket输出流*/
import java.net.*;
import java.io.*;
import java.util.*;
class TCPServer2313 
{
	public static void main(String[] args) throws Exception
	{
		server(10000);
	}
	public static void server(int num)throws Exception
	{
		//接受客户端发送的信息2
		ServerSocket ss=new ServerSocket(num);
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println("ip:"+ip+"-------connect");
		//socket读取流
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		//BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		//可改为:
		PrintWriter bufOut=new PrintWriter(s.getOutputStream(),true);//true为自动刷新

		String line=null;
		while((line=bufIn.readLine())!=null)
		{
			System.out.println("客户端发过来的信息:"+line);
			//给客户端发送信息3
			//bufOut.write(line.toUpperCase());
			//bufOut.newLine();//因为客户端的readLine()是阻塞式的,判断结束的标记是回车符
			//bufOut.flush();//写入到的是缓冲区中,需刷新
			//可改为:
			bufOut.println("服务端返回的数据是:"+line.toUpperCase());
		}
		ss.close();
	}
}

打开服务端:

客户端:

分析:
客户端:既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考
源:键盘录入
目的:设备网络,设备输出流
操作的是文本数据,可以选择字符流
步骤:1.建立服务
	  2.获取键盘录入
	  3.将数据发送给服务端
	  4.接收服务端返回的大写数据(3,4.....)
	  5.结束,关闭资源
都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲
*/
import java.net.*;
import java.io.*;
class TCPClient2313 
{
	public static void main(String[] args) throws Exception
	{
		client("192.168.1.111",10000);
	}
	public static void client(String str,int num) throws Exception
	{	
		Socket s=new Socket(str,num);
		//源:定义读取键盘数据的流对象。
		//读取:输进来的是字节流,要用的是字符流,所以要用InputStreamReader
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		//目的:将数据写入到socket输出流中,发送给服务端
		//输出:现在的是字符流,要发送出去的是字节流,所以要用OutputStreamWriter
		//BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		//BufferedWriter:缓冲区具有newLine();可改为:
		PrintWriter bufOut=new PrintWriter(s.getOutputStream(),true);//true为自动刷新

		//定义一个socket读取流,读取服务端返回的大写信息;BufferedReader:缓冲区具有readLine();
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line=null;
		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			//发送信息到服务器端1
			//bufOut.write(line);
			//bufOut.newLine();//因为客户端的readLine()是阻塞式的,判断结束的标记是回车符
			//bufOut.flush();//当写入一行,写入到的是缓冲区中
			//可改为:
			bufOut.println(line);

			//读取服务器端发送的数据4
			String value=bufIn.readLine();
			System.out.println(value);
		}
		bufr.close();
        //当socket关闭,其带有的读取流(getInputStream),关闭流(getOutputStream)也会随之关闭
		s.close();//当socket关闭后,readLine的结束标记为-1,所以服务端也会结束
	}
}
/*该例出现的问题
现象:客户端和服务端都在莫名的等待
原因是:客户端和服务端都有阻塞式方法,这些方法没有读到结束标记,就会一直等,
而导致两端都在等待*/

客户端运行,传输数据并且返还的数据:

服务端接收的数据:

练习2:网络间文件复制

客户端:

分析:1.建立socket
	  2.将本地文件发送到服务端
	  源:是纯文本,用Reader,硬盘,FileReader
	  目的:是纯文本,用Writer,硬盘,FileWriter*/
import java.net.*;
import java.io.*;
import java.util.*;
class TCPClient2314 
{
	public static void main(String[] args)  throws Exception
	{
		Socket s=new Socket("192.168.1.111",10001);
		BufferedReader bufr=new BufferedReader(new FileReader("TCPClient2313.java"));
		//BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		//可转换成:
		PrintWriter bufOut=new PrintWriter(s.getOutputStream(),true);
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		//结束方式1:建立时间戳,来解决两边都等待的问题
		//long time=System.currentTimeMillis();
		//bufOut.println(time+"");
		//可改为:
		//DataOutputStream dos=new DataOutputStream(s.getOutputStream());
		//long time=System.currentTimeMillis();
		//dos.writeLong(time);
		
		String line=null;
		while((line=bufr.readLine())!=null)
		{
			/*bufOut.write(line);
			bufOut.newLine();
			bufOut.flush();*/
			bufOut.println(line);
		}
		//结束方式2:
		s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1
		System.out.println(bufIn.readLine());
		bufr.close();
		s.close();
	}
}

服务端:

分析:1.建立serversocket
	  2.接收客服端发送过来的文件,并保存在本机上*/
import java.net.*;
import java.io.*;
import java.util.*;
class TCPServer2314 
{
	public static void main(String[] args)  throws Exception
	{
		ServerSocket ss=new ServerSocket(10001);
		Socket s=ss.accept();
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String ip=s.getInetAddress().getHostAddress();
		System.out.println("ip:"+ip+"-------connect");
		//BufferedWriter bufw=new BufferedWriter(new FileWriter("D:\\TCPClick2313.java"));
		//可转换成:
		PrintWriter bufw=new PrintWriter(new FileWriter("D:\\TCPClient2313.java"),true);

		//BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		//可转换成:
		PrintWriter bufOut=new PrintWriter(s.getOutputStream(),true);
        /*//结束方式1:
		DataInputStream dis=new DataInputStream(s.getInputStream());
		long time=dis.readLong();//获取时间戳,然后,判断时间戳(结束标记)
		long currentTime=System.currentTimeMillis();
		System.out.println("curr:"+currentTime+"-time"+time);*/

		String line=null;
		while((line=bufIn.readLine())!=null)
		{
			//if(time!=currentTime)
				//break;
			/*bufw.write(line);
			bufw.newLine();
			bufw.flush();*/
			bufw.println(line);
		}
		bufOut.println("发送成功!");
		bufw.close();
		s.close();
		ss.close();
	}
}
/*结束方式:
    方法1:
	根据判断标记,可用判断时间戳
	//建立时间戳,因为时间是唯一的,来解决两边都等待的问题
	//long time=System.currentTimeMillis();
	//bufOut.println(time+"");
	//DataInputStream dis=new DataInputStream(s.getInputStream());
	//long time=dis.readLong();//获取时间戳,然后再去跟当前时间判断(结束标记)
	方法2:
	socket中的shutdownOutput()://关闭客户端的输出流,相当于给流中加入一个结束标记-1
	shutdownInput()
*/

练习3:上传图片,并发上传图片

客户端:

分析:
1.建立socket
2.源:不是纯文本,字节流,硬件,FileInputStream
  目的:传给服务端,不是纯文本,字节流,硬件,FileOutputStream*/
import java.net.*;
import java.io.*;
import java.util.*;
class TCPClient2401
{
	public static void main(String[] args)  throws Exception
	{
		//给主函数传值。cmd中:java TCPClick2401 d:\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"))
		{
			System.out.println("请上传jpg格式的图片"+file.getName());
			return;
		}
		if(file.length()>1024*1024*8)
		{
			System.out.println("图片太大了......");
			return;
		}

		Socket s=new Socket("192.168.1.111",10002);
		FileInputStream fin=new FileInputStream (file);
        OutputStream out=s.getOutputStream();
		int len;
		byte[] buf=new byte[1024];
		while((len=fin.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));		
		fin.close();
		s.close();
	}
}

服务端:

import java.net.*;
import java.io.*;
import java.util.*;
class TCPServer2401
{
	public static void main(String[] args)  throws Exception
	{
		ServerSocket ss=new ServerSocket(10002);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new PicThread(s)).start();
		}
		//ss.close();
	}
	public static void server() throws Exception
	{
		ServerSocket ss=new ServerSocket(10002);
		while (true)
		{
			Socket s=ss.accept();
			String ip=s.getInetAddress().getHostAddress();
			System.out.println("ip:"+ip+"------connect");

			InputStream in=s.getInputStream();
			FileOutputStream fos=new FileOutputStream("D:\\Mine_Huan\\11.jpg");
			int len=0;
			byte[] buf=new byte[1024];
			while((len=in.read(buf))!=-1)
			{
				fos.write(buf,0,len);
			}
			OutputStream out=s.getOutputStream();
			out.write("上传成功".getBytes());
			fos.close();
			s.close();
		}
		//ss.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:"+ip+"------connect");
			InputStream in=s.getInputStream();
			File file=new File(ip+"("+(count)+").jpg");		
			while(file.exists())
			{
				 file=new File(ip+"("+(count++)+").jpg");
			}
			FileOutputStream fos=new FileOutputStream(file);
			int len=0;
			byte[] buf=new byte[1024];
			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+"出错了");
		}	
	}
}

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

客户端:

import java.net.*;
import java.io.*;
import java.util.*;
class  TCPClient2403
{
	public static void main(String[] args)  throws Exception
	{
		Socket s=new Socket("192.168.1.111",10003);
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		OutputStream out=s.getOutputStream();
		PrintWriter pw=new PrintWriter(out,true);
		InputStream in=s.getInputStream();
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(in));
		for(int i=0;i<3;i++)//最多就登陆三次
		{
			String line=bufr.readLine();
			if(line==null)
				break;
			pw.println(line);

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

服务端:

分析:1.获取客户端发送过来的信息与本地的用户文件(user2403.txt)进行比较判断*/
import java.net.*;
import java.io.*;
import java.util.*;
class Server implements Runnable
{
	private Socket s;
	Server(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		int count=0;
		String ip=s.getInetAddress().getHostAddress();	
		System.out.println("ip:"+ip+"------connect");
		try
		{
			for(int i=0;i<3;i++)
			{			
				InputStream in=s.getInputStream();
				BufferedReader bufIn=new BufferedReader(new InputStreamReader(in));
				BufferedReader bufr=new BufferedReader(new FileReader("user2403.txt"));
				OutputStream out=s.getOutputStream();
				PrintWriter pw=new PrintWriter(out,true);
				String line=null;
				String user=bufIn.readLine();
				if(user==null)
					break;
				boolean flag=false;//标记
				while((line=bufr.readLine())!=null)
				{
					if(line.equals(user))
					{
						flag=true;
						break;
					}
				}
				if(flag)
				{
					System.out.println(user+"已登陆");
					pw.println(user+"欢迎光临");
					break;
				}
				else
				{
					System.out.println(user+"尝试登陆");
					pw.println(user+"该用户不存在");
				}
			}
			s.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException(ip+"登陆失败");
		}		
	}
}
class  TCPServer2403
{
	public static void main(String[] args)  throws Exception
	{
		ServerSocket ss=new ServerSocket(10003);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new Server(s)).start(); 
		}
		
	}
}

练习5:客户端:浏览器,服务端:自定义

客户端:

import java.net.*;
import java.io.*;
import java.util.*;
class  TCPClient2404
{
	public static void main(String[] args)  throws Exception
	{
		Socket s=new Socket("192.168.1.111",10004);
		OutputStream out=s.getOutputStream();
		PrintWriter pw=new PrintWriter(out,true);
		pw.println("GET /JavaExercise/myhtml HTTP/1.1");
		//pw.println("GET /Mine_Huan/MyFile/JavaExercise/myhtml HTTP/1.1");
		pw.println("Accept: */*");
		pw.println("Accept-Language: en-US");
		pw.println("Host: 192.168.139.1:10004");
		pw.println("Connection: closed");
		pw.println();
		pw.println();
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line=null;
		while((line=bufIn.readLine())!=null)
		{
			System.out.println(line);
		}
		s.close();
	}
}

服务端:

import java.net.*;
import java.io.*;
import java.util.*;
class  TCPServer2404
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss=new ServerSocket(10004);
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();	
		System.out.println("ip:"+ip+"------connect");

		InputStream in=s.getInputStream();
		byte[] buf=new byte[1024];
		int len=in.read(buf);//读取浏览器发送过来的信息	
		System.out.println(new String(buf,0,len));

		OutputStream out=s.getOutputStream();
		PrintWriter pw=new PrintWriter(out,true);
		pw.println("<font color='red' size='7'>Hello World!</font>");
		s.close();
		ss.close();
	}
}
//要先启动服务端(cmd),在浏览器中输入本机ip+访问端口即可访问服务端
//如:http://192.168.139.1:10004
//telnet:远程登陆命令,可以连接其它主机(相当于客户端)
//如:在cmd中:telnet 192.168.139.1 10004
//ip:192.168.139.1------connect

/**浏览器发送过来的信息:
GET /JavaExercise/myhtml HTTP/1.1
Accept: text/html, application/xhtml+xml, 
Accept-Language: en-US,en;q=0.5
User-Agent: Mozilla/5.0 (MSIE 9.0; Windows NT 6.3; WOW64; Trident/7.0; rv:11.0)
like Gecko
DontTrackMeHere: gzip, deflate
Host: 192.168.139.1:10004
DNT: 1
Connection: Keep-Alive

*/

 注:浏览器发送给服务器的是:”HTTP的请求消息头“信息,第一行是请求行,最后一行空行的下面是:请求数据体;对应的还有”应答请求信息“。

三、URL对象和URLConnection对象

URL:代表一个统一资源定位符,它是指向互联网“资源”的指针。即域名

方法:

       1.String getProtocol():获取协议名称

       2.String getHost():获取主机名

       3.int getPort():获取端口号

       4.String getFile():获取URL文件名

       5.String getPath():获取URL的路径部分

       6.String getQuery():获取URL的查询部,客户端传输的特定信息

注:如果URL的路径出错,会报MalformedURLException异常。

       如当IP地址为192.168.1.254,当为254时,端口号为-1,默认其端口号为:80。

URLConnection类:是一个远程连接对象

 如:URL url=new URL("http://write.blog.csdn.net/postedit/46698635");//创建URL对象

        URLConnection conn=url.openConnection();//连接指定主机,返回一个远程连接对象

        InputStream in=conn.getInputStream();

        byte[] buf=new byte[1024];

        int len=in.read(buf);

        System.out.println(buf,0,len);

小知识:

    1.如果想将主机名翻译成IP地址,需要域名解析DNS(域名解析服务器)。

  如:想登录www.sina.com.cn。需要先找DNS,通过DNS获取新浪IP地址,客户端再通过IP查找主机,但是它先要在本地主机上先查找再找DNS。

  2.http://127.0.0.1:8080http://localhost:8080:其实127和localhost的映射关系就在本地机子上,在”c:\windows\system32\drivers\ext\host“中,修改127和localhost的映射关系,可以有效的屏蔽恶意网站。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值