黑马程序员----java基础--网络编程

 一、 网络参考模型

1、OSI参考模型和TCP/IP 参考模型

七层描述:

(1). 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流。

(2). 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。这一层工作的设备是交换机,数据通过交换机来传输。

(3). 网络层:主要将下层接收到的数据进行IP地址(例,192.168.0.1)的封装与解封装。这一层工作的设备是路由器。。

(4). 传输层:定义了一些传输数据的协议和端口号(WWW端口号80等),主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。

(5). 会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接收会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。

(6). 表示层:主要是进行对接收的数据进行解释,加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够识别的东西(如图片、声音等)。

(7). 应用层:主要是一些终端的应用,比如说FTP(各种文件下载)、WEB(IE浏览)、QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西,就是终端应用)。

注:

(1).每个网卡的MAC地址都是全球唯一的。

(2).路由器实现将数据包发送到指定的地点。

(3).应用软件之间通信的过程就是层与层之间封包、解包的过程

(4).OSI参考模型虽然设计精细,但过于麻烦,效率不高,因此才产生了简化版的TCP/IP参考模型。

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

(1)、IP地址:InetAdderss类

1.它是网络中的设备标识

2.不易记忆,可用主机名表示,两者存在映射关系

3.IPV4数量已经不够分配,所以产生了IPV6

4.本地回环地址:127.0.0.1 主机名:localhost

5.在没有连接互联网的情况,为了让访问本机方便,所以分配了一个默认的IP地址,也就是本地回环地址

(2)、端口号

1.用于标识进程(应用程序)的逻辑地址,不同进程的标识

2.有效端口:0~65535,其中0~1024系统使用或保留端口。

3.没有程序都有端口号用来定为应用程序

(3)、传输协议

这是通讯的规则。常见协议有:UDP、TCP。

UDP

1.将数据以及源和目的封装成数据包中,不需要建立连接

2.每个数据包的大小限制在64k内

3.因无连接,所以是不可靠的协议

4.不需要建立连接,速度快

应用案例:QQ聊天、视频聊天、对讲机、FeiQ、视频教学等在线视频都是UDP

TCP

1.建立连接,形成传输数据的通道

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

3.通过三次握手完成连接,是可靠协议。三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方确认对方连接成功。

4.必须建立连接,效率会稍低

应用案例:FTP文件传输、迅雷下载、打电话

3、java.net.InetAdderss常用网络方法

无构造函数,只能用方法返回本类对象


  1. static  InetAddress    getLocalHost();//返回一个InetAdderss本类对象 
  2. static  String    getHostName();//返回此ip地址的主机名 
  3. static   String    getHostAddress();//返回ip地址字符串 
  4. String    toString();//返回此ip地址的String表现形式 
  5. static    InetAddress    getByName(String host);//获取指定主机名的ip地址 
  6. static  InetAddress[]    getAllByName(String host);//获取指定主机名的全部ip地址 

代码演示:


  1. import java.net.*; 
  2. class InetAddressDemo  
  3.     public static void main(String[] args) throws Exception 
  4.     { 
  5.         InetAddress ia= InetAddress.getLocalHost();//返回InetAddress本来对象 
  6.         String name=ia.getHostName();//获取IP地址的主机名 
  7.         String ip=ia.getHostAddress();//获取本地ip地址 
  8.         System.out.println("name="+name); 
  9.         System.out.println("ip="+ip); 
  10.  
  11.         InetAddress i=InetAddress.getByName("192.168.1.1");//获取指定主机的IP 地址 
  12.         System.out.println(i.getHostAddress()); 
  13.  
  14.         InetAddress[] ina=InetAddress.getAllByName("www.sina.com.cn");//获取指定主机名的全部ip地址 
  15.         for (InetAddress a:ina ) 
  16.         { 
  17.             System.out.println(a.getHostAddress()); 
  18.             System.out.println(a.getHostName()); 
  19.         } 
  20.     } 

二、UDP协议-发送端和接收端

Socket:套接字,通信的端点。就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。

1、DatagramSocket和DatagramPacket对象

(1)、DatagramSocket类常用方法

此类表示用来发送和接收数据报包的套接字。

1、构造方法

1 new DatagramSocket();//构造数据报套接字并绑定到本地主机任何端口上,发送端
2 new DatagramSocket(int port);//创建数据报套接字并绑定到本地主机上的指定端口,接收端

2、一般方法

1 void connect(InetAddress address,int port);//将套接字连接到此套接字的远程地址上
2 void send(DatagramPacket p);//从此套接字发送数据包
3 void receive(DatagramPacket p);//从此套接字接收数据包
4 InetAddress getInetAddress();//返回此套接字连接的地址
5 int getPort();//返回此套接字的端口

(2)、DatagramPacket类常用方法

此类表示数据报包

1、构造方法

1 new DatagramPacket(byte[] buf,int length,InetAddress address,int port);//构造数据报包,用来将长度为length的包发送到指定主机上的指定端口号
2 newDatatgramPacket(byte[] buf,int length);//构造 DatagramPacket,用来接收长度为 length 的数据包

2、一般方法

1 InetAddress getAddress();//获取某台主机的ip地址
2 byte[] getData();//获取数据缓冲区的内容
3 int getLength();//获取将要发送或者接收到的数据的长度
4 int getPort();//获取某台主机的端口号

2、UDP传输发送和获取数据的步骤

UDP发送端步骤:

1)、建立UDPSocket服务

2)、提供数据,并将数据封装到数据包中

3)、通过Socket服务的send方法,将数据包发送出去

4)、关闭资源

UDP接收端步骤:

1)、定义UDPSocket服务。通常会监听一个端口号。其实就是给这个接收网络应用程序定义数字标识,方便于明确哪些数据过来哪个应该程序可以处理

2)、定义一个数据包。因为要存储接收到的字节数据。因为数据包对象中有更多功能可以提取字节数据中的不同数据信息

3)、通过Sockt服务的receive方法将接收到的数据存入已经定义好的数据包中

4)、通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上

5)、关闭资源

需求:聊天程序(双窗口模式)代码演示:


  1. import java.io.*; 
  2. import java.net.*; 
  3. class UDPSend  
  4.     public static void main(String[] args)  
  5.     { 
  6.         DatagramSocket ds=null;         
  7.         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  8.         try         
  9.         { 
  10.             //1,创建udp服务。通过DatagramSocket对象。 
  11.             ds=new DatagramSocket(); 
  12.             String line=null; 
  13.             while ((line=br.readLine())!=null) 
  14.             { 
  15.                 byte[] buf=line.getBytes(); 
  16.                 //2,确定数据,并封装成数据包。DatagramPacket(byte[] buf,int length, InetAddress address, int port)  
  17.                 DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.104"),55128); 
  18.                 //3,通过socket服务,将已有的数据包发送出去。通过send方法 。 
  19.                 ds.send(dp); 
  20.                 if("over".equals(line)) 
  21.                     break; 
  22.             } 
  23.              
  24.         } 
  25.         catch (Exception e) 
  26.         { 
  27.             System.out.println(e); 
  28.         } 
  29.         finally 
  30.         { 
  31.             if(ds!=null) 
  32.                 try 
  33.                 { 
  34.                     //4,关闭资源。 
  35.                     ds.close(); 
  36.                 } 
  37.                 catch (Exception e) 
  38.                 { 
  39.                     System.out.println("发送端关闭失败"); 
  40.                 } 
  41.         } 
  42.     } 
  43. class UDPReceive 
  44.     public static void main(String[] args){ 
  45.         DatagramSocket ds=null; 
  46.         DatagramPacket dp=null; 
  47.         try{ 
  48.             //1,创建udp socket,建立端点。 
  49.             ds=new DatagramSocket(55128);         
  50.             while (true) 
  51.             {    //2,定义数据包。用于存储数据。             
  52.                 byte[] buf=new byte[1024]; 
  53.                 dp=new DatagramPacket(buf,buf.length); 
  54.                 //3,通过服务的receive方法将收到数据存入数据包中。 
  55.                 ds.receive(dp);//阻塞式方法。 
  56.                 //4,通过数据包的方法获取其中的数据。 
  57.                 String ip=dp.getAddress().getHostAddress(); 
  58.                 String data=new String(dp.getData(),0,dp.getLength()); 
  59.                 System.out.println(ip+"......"+data); 
  60.                 if(data.equals("over")) 
  61.                     break; 
  62.             } 
  63.              
  64.         } 
  65.         catch (Exception e) 
  66.         { 
  67.             System.out.println(e); 
  68.         } 
  69.         finally 
  70.         { 
  71.             if(ds!=null) 
  72.                 try 
  73.                 { 
  74.                     //5,关闭资源 
  75.                     ds.close(); 
  76.                 } 
  77.                 catch (Exception e) 
  78.                 { 
  79.                     System.out.println("接收端关闭失败"); 
  80.                 } 
  81.         } 
  82.     } 

需求:聊天程序(单窗口模式-群聊)代码演示:

收数据的部分,和发数据的这两部分需要同时执行。那就需要用到多线程技术。一个线程控制收,一个线程控制发。因为收和发动作是不一致的,所以要定义两个run方法。而且这两个方法要封装到不同的类中。


  1. import java.io.*; 
  2. import java.net.*; 
  3. class UDPSend implements Runnable 
  4.     private DatagramSocket ds; 
  5.     UDPSend(DatagramSocket ds){ 
  6.         this.ds=ds; 
  7.     } 
  8.     public void run(){ 
  9.         try 
  10.         { 
  11.             //读取键盘录入 
  12.             BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  13.             String line=null; 
  14.             while ((line=br.readLine())!=null) 
  15.             { 
  16.                 byte[] buf=line.getBytes(); 
  17.                 //定义数据包,用来存放数据 
  18.                 DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.104"),5556); 
  19.                 //通过send方法把数据发送给接收端 
  20.                 ds.send(dp); 
  21.                 if("over".equals(line)) 
  22.                     break; 
  23.             } 
  24.             ds.close(); 
  25.         } 
  26.         catch (Exception e) 
  27.         { 
  28.             System.out.println("发送失败"); 
  29.         } 
  30.     } 
  31. class UDPReceive implements Runnable 
  32.     private DatagramSocket ds; 
  33.     UDPReceive(DatagramSocket ds){ 
  34.         this.ds=ds; 
  35.     } 
  36.     public void run(){//复写run方法 
  37.         try 
  38.         { 
  39.             while (true) 
  40.             { 
  41.                 byte[] buf=new byte[1024]; 
  42.                 //定义数据包用来接收发送端发过来的数据信息 
  43.                 DatagramPacket dp=new DatagramPacket(buf,buf.length); 
  44.                 //接收数据 
  45.                 ds.receive(dp); 
  46.                 //对接收过来的数据进行ip地址等信息的解析 
  47.                 String ip=dp.getAddress().getHostAddress(); 
  48.                 String data=new String(dp.getData(),0,dp.getLength()); 
  49.                 System.out.println(ip+"......."+data); 
  50.                 if("over".equals(data)) 
  51.                     break; 
  52.             } 
  53.             ds.close();             
  54.         } 
  55.         catch (Exception e) 
  56.         { 
  57.             System.out.println("接收端接受失败"); 
  58.         } 
  59.     } 
  60. class ChatRoom 
  61.     public static void main(String[] args)throws Exception{ 
  62.         //定义两个DatagramSocket服务 
  63.         DatagramSocket send=new DatagramSocket(); 
  64.         DatagramSocket receive=new DatagramSocket(5556); 
  65.         //开启两个线程 
  66.         new Thread(new UDPSend(send)).start(); 
  67.         new Thread(new UDPReceive(receive)).start(); 
  68.     } 

三、TCP协议-客户端和服务端

客户端(Client)首先与服务端(Server)建立连接,形成通道(其实就是IO流),然后,数据就可以在通道之间进行传输,并且单个Server端可以同时与多个Client端建立连接。Socket和ServerSocket,建立客户端和服务器端。建立连接后,通过Socket中的IO流进行数据的传输。关闭socket。同样,客户端与服务器端是两个独立的应用程序。

TCP客户端

客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream()和getOutputStream()获取即可与服务端通讯。结束后关闭Socket。客户端,通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

TCP服务端

服务端需要明确它要处理的数据是从哪个端口进入的。当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。当该客户端访问结束,关闭该客户端。1,建立服务端的socket服务。ServerSocket();并监听一个端口。2,获取连接过来的客户端对象。通过ServerSokcet的

accept方法。没有连接就会等,所以这个方法阻塞式的。3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。并打印在控制台。4,关闭服务端。(可选)。

TCP协议因为是面向连接的。所以传输数据必须先开服务端,再开客户端。否则,客户端根本连接不上服务端。

1、Socket类中常用方法

(1)、构造方法

1 new Socket();
2 new Socket(InetAddress address,int port);//创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
3 new Socket(String host,int port);// 创建一个流套接字并将其连接到指定主机上的指定端口号。

(2)、成员方法


  1. void  bind(SocketAddress bindpoint);//将套接字绑定到本地地址。  
  2. void  connect(SocketAddress endpoint);//将此套接字连接到服务器。  
  3. InetAddress  getInetAddress();//返回套接字连接的地址。 
  4. InputStream  getInputStream();//返回此套接字的输入流。 
  5. OutputStream  getOutputStream();// 返回此套接字的输出流。  
  6. int  getPort();// 返回此套接字连接到的远程端口  
  7. void  shutdownInput();// 此套接字的输入流置于“流的末尾”。  
  8. void  shutdownOutput();// 禁用此套接字的输出流 

2、ServerSocket类中常用方法

(1)、构造方法

1 new ServerSocket();//创建非绑定服务器套接字。
2 new ServerSocket(int port);//创建绑定到特定端口的服务器套接字。

(2)、成员方法

1 Socket accept();//侦听并接受到此套接字的连接。
2 InetAddress getInetAddress();// 返回此服务器套接字的本地地址。

需求:TCP协议-服务端和客户端交互代码演示:


  1. import java.io.*; 
  2. import java.net.*; 
  3. class  TCPClient 
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         //创建客户端的socket服务。指定目的主机和端口 
  7.         Socket s=new Socket("192.168.1.100",5544); 
  8.         //为了发送数据,应该获取socket流中的输出流。 
  9.         OutputStream out=s.getOutputStream(); 
  10.         out.write("TCP,我来了!".getBytes()); 
  11.         InputStream in=s.getInputStream(); 
  12.         byte[] buf=new byte[1024]; 
  13.         int len=in.read(buf); 
  14.         System.out.println(new String(buf,0,len)); 
  15.         s.close(); 
  16.     } 
  17. class TCPServer 
  18.     public static void main(String[] args)throws Exception{ 
  19.         //建立服务端socket服务。并监听一个端口。 
  20.         ServerSocket ss=new ServerSocket(5544); 
  21.         //通过accept方法获取连接过来的客户端对象。 
  22.         Socket s=ss.accept(); 
  23.         //获取ip地址 
  24.         String ip=s.getInetAddress().getHostAddress(); 
  25.         System.out.println(ip+".....connnect"); 
  26.         //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。 
  27.         InputStream in=s.getInputStream(); 
  28.         byte[] buf=new byte[1024]; 
  29.         int len=in.read(buf); 
  30.         System.out.println(new String(buf,0,len)); 
  31.  
  32.         OutputStream out=s.getOutputStream(); 
  33.         out.write("收到".getBytes()); 
  34.         ss.close(); 
  35.         //关闭客户端. 
  36.         s.close(); 
  37.     } 

需求:建立一个文本转换服务器。

客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。

客户端:

既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。

源:键盘录入。

目的:网络设备,网络输出流。

而且操作的是文本数据。可以选择字符流。

步骤

1,建立服务。

2,获取键盘录入。

3,将数据发给服务端。

4,后去服务端返回的大写数据。

5,结束,关资源。

都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。

服务端:

源:socket读取流。

目的:socket输出流。

都是文本,装饰。


  1. import java.io.*; 
  2. import java.net.*; 
  3. class TransClient  
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.100",7788); 
  7.         //定义读取键盘数据的流对象。 
  8.         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  9.         //定义目的,将数据写入到socket输出流。发给服务端。 
  10.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  11.         //定义一个socket读取流,读取服务端返回的大写信息。 
  12.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  13.         String line=null; 
  14.         while ((line=br.readLine())!=null) 
  15.         { 
  16.             out.println(line); 
  17.             if("over".equals(line)) 
  18.                 break; 
  19.             String info=in.readLine();         
  20.             System.out.println("info="+info); 
  21.         } 
  22.         s.close(); 
  23.  
  24.     } 
  25. class TransServer 
  26.     public static void main(String[] args)throws Exception{ 
  27.         ServerSocket ss=new ServerSocket(7788);         
  28.         Socket s=ss.accept(); 
  29.         System.out.println(s.getInetAddress().getHostAddress()+".....connect"); 
  30.         //读取socket读取流中的数据。 
  31.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  32.         //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。 
  33.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  34.         String line=null; 
  35.         while ((line=in.readLine())!=null) 
  36.         { 
  37.             System.out.println(line); 
  38.             out.println(line.toUpperCase()); 
  39.             if("over".equals(line)) 
  40.                 break; 
  41.         } 
  42.         s.close(); 
  43.         ss.close(); 
  44.     } 

需求:TCP协议上传文本文件


  1. import java.io.*; 
  2. import java.net.*; 
  3. class  TCPClient 
  4.     public static void main(String[] args)throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.100",9999); 
  7.         BufferedReader br=new BufferedReader(new FileReader("TCPDemo.java")); 
  8.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  9.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  10.         String line=null; 
  11.         while ((line=br.readLine())!=null) 
  12.         { 
  13.             out.println(line); 
  14.         } 
  15.         s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1. 
  16.         System.out.println(in.readLine()); 
  17.         s.close(); 
  18.         br.close(); 
  19.     } 
  20. class TCPServer 
  21.     public static void main(String[] args)throws Exception{ 
  22.         ServerSocket ss=new ServerSocket(9999); 
  23.         Socket s=ss.accept(); 
  24.         System.out.println(s.getInetAddress().getHostAddress()+"....connect"); 
  25.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  26.         PrintWriter pw=new PrintWriter(new FileWriter("E:\\TCPDemo.java"),true); 
  27.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  28.         String line=null; 
  29.         while ((line=in.readLine())!=null) 
  30.         { 
  31.             pw.println(line); 
  32.         } 
  33.         out.println("上传成功"); 
  34.         s.close(); 
  35.         ss.close(); 
  36.         pw.close(); 
  37.     } 

需求:TCP客户端并发上传图片代码演示:

服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。

如何定义线程呢?

只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。


  1. import java.io.*; 
  2. import java.net.*; 
  3. class PicClient 
  4.     public static void main(String[] args)throws Exception{ 
  5.         File file=new File(args[0]); 
  6.         if(!(file.exists()&& file.isFile())){ 
  7.             System.out.println("请上传图片"); 
  8.             return; 
  9.         } 
  10.         if(!(file.getName().endsWith(".jpg"))){ 
  11.             System.out.println("上传格式错误"); 
  12.             return; 
  13.         } 
  14.         if(file.length()>=1024*1024*4){ 
  15.             System.out.println("文件过大,请切割后上传"); 
  16.             return; 
  17.         } 
  18.  
  19.         Socket s=new Socket("192.168.1.104",5555); 
  20.         FileInputStream fis=new FileInputStream(file); 
  21.         OutputStream out=s.getOutputStream(); 
  22.         byte[] buf=new byte[1024]; 
  23.         int len=0; 
  24.         while ((len=fis.read(buf))!=-1) 
  25.         { 
  26.             out.write(buf,0,len); 
  27.         } 
  28.         s.shutdownOutput();//告诉服务端数据已写完 
  29.         InputStream in=s.getInputStream(); 
  30.         byte[] bufIn=new byte[1024]; 
  31.         int num=in.read(bufIn); 
  32.         System.out.println(new String(bufIn,0,num)); 
  33.         s.close(); 
  34.         fis.close(); 
  35.     } 
  36. class PicThread implements Runnable 
  37.     private Socket s; 
  38.     PicThread(Socket s){ 
  39.         this.s=s; 
  40.     } 
  41.     public void run(){ 
  42.         String ip=s.getInetAddress().getHostAddress(); 
  43.         System.out.println(ip+".....connect"); 
  44.         try 
  45.         { 
  46.             int count=1; 
  47.             //创建file对象 
  48.             File file=new File("E:\\"+ip+"("+count+")"+".jpg"); 
  49.             //如果file文件存在则count++,直到不存在为止 
  50.             while(file.exists()) 
  51.                 file=new File("E:\\"+ip+"("+(count++)+")"+".jpg"); 
  52.             InputStream in=s.getInputStream(); 
  53.             FileOutputStream fos=new FileOutputStream(file); 
  54.             byte[] buf=new byte[1024]; 
  55.             int len=0; 
  56.             while ((len=in.read(buf))!=-1) 
  57.             { 
  58.                 fos.write(buf,0,len); 
  59.             } 
  60.             OutputStream out=s.getOutputStream(); 
  61.             out.write("上传成功".getBytes()); 
  62.             s.close();             
  63.         } 
  64.         catch (Exception e) 
  65.         { 
  66.             System.out.println(ip+"连接成功"); 
  67.         } 
  68.     } 
  69. class PicServer 
  70.     public static void main(String[] args)throws Exception{ 
  71.         ServerSocket ss=new ServerSocket(5555); 
  72.         while (true) 
  73.         { 
  74.             Socket s=ss.accept(); 
  75.             new Thread(new PicThread(s)).start(); 
  76.         } 
  77.     } 

需求:客户端通过键盘录入用户名。服务端对这个用户名进行校验。最多就登录三次。

如果该用户存在,在服务端显示xxx,已登陆。

并在客户端显示 xxx,欢迎光临。

如果该用户不存在,在服务端显示xxx,尝试登陆。

并在客户端显示 xxx,该用户不存在。


  1. import java.io.*; 
  2. import java.net.*; 
  3. class LoginClient  
  4.     public static void main(String[] args)throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.104",6666); 
  7.         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  8.         //读取socket流中的读取流 
  9.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  10.         //socket流中的输出流 
  11.         PrintWriter out=new PrintWriter(s.getOutputStream(),true);     
  12.         //循环3次输入,如果输入为null,直接停止输入 
  13.         for (int x=0;x<3 ;x++ ) 
  14.         { 
  15.             String name=br.readLine(); 
  16.             if(name==null) 
  17.                 break; 
  18.             out.println(name); 
  19.             String info=in.readLine(); 
  20.             System.out.println(info); 
  21.             //如果获取到流中有“欢迎“字样,说明对方已经登录,这时候即使输入的不到3次,也停止输入,因为已经登录成功了。 
  22.             if(info.contains("欢迎")){                 
  23.                 break; 
  24.             } 
  25.         } 
  26.         s.close(); 
  27.     } 
  28. class LoginThread implements Runnable 
  29.     private Socket s; 
  30.     LoginThread(Socket s){ 
  31.         this.s=s; 
  32.     } 
  33.     public void run(){ 
  34.         String ip=s.getInetAddress().getHostAddress(); 
  35.         System.out.println(ip+".....connect"); 
  36.         try 
  37.         {                 
  38.             for (int x=0;x<3 ;x++ ) 
  39.             { 
  40.                 //读取socket流中的输入流 
  41.                 BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  42.                 String name=in.readLine(); 
  43.                 if(name==null) 
  44.                     break; 
  45.                 //读取文件 
  46.                 BufferedReader br=new BufferedReader(new FileReader("Userinfo.txt")); 
  47.                 //socket流输出流 
  48.                 PrintWriter out=new PrintWriter(s.getOutputStream(),true);     
  49.                 //定义一个标记, 从socket输入流中的键盘数据判断user.txt中是否有name符合,如果有标记为真,跳出while循环。 
  50.                 boolean flag=false; 
  51.                 String line=null; 
  52.                 while ((line=br.readLine())!=null) 
  53.                 { 
  54.                     //判断Userinfo.txt和name是否有相同的 
  55.                     if(line.equals(name)){ 
  56.                         flag=true; 
  57.                         break; 
  58.                     } 
  59.                 } 
  60.                 if(flag){ 
  61.                     System.out.println(name+",已登陆"); 
  62.                     out.println(name+",欢迎光临"); 
  63.                     break; 
  64.                 } 
  65.                 else{ 
  66.                     System.out.println(name+",尝试登陆"); 
  67.                     out.println(name+",该用户不存在"); 
  68.                 } 
  69.             } 
  70.             s.close(); 
  71.         } 
  72.         catch (Exception e) 
  73.         { 
  74.             System.out.println(ip+"连接失败"); 
  75.         } 
  76.     } 
  77. class LoginServer 
  78.     public static void main(String[] args)throws Exception{ 
  79.         ServerSocket ss=new ServerSocket(6666); 
  80.         while (true) 
  81.         { 
  82.             Socket s=ss.accept(); 
  83.             new Thread(new LoginThread(s)).start(); 
  84.         } 
  85.     } 

四、客户端和服务器端原理

最常见的客户端:浏览器,IE/chrome。

最常见的服务端:服务器,Tomcat。

1. 自定义服务端

使用已有的客户端IE,了解一下客户端向服务端发了什么请求


  1. import java.io.*; 
  2. import java.net.*; 
  3. class ServerDemo  
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         ServerSocket  ss=new ServerSocket(8080); 
  7.         Socket s=ss.accept(); 
  8.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  9.         out.println("<font size='5' color='red'>客户端你好 </font>"); 
  10.         //获取到服务器向客户端发送的数据 
  11.         InputStream is=s.getInputStream();         
  12.         byte[] buf=new byte[1024];         
  13.         int len=is.read(buf); 
  14.         System.out.println(new String(buf,0,len)); 
  15.         ss.close(); 
  16.         s.close();         
  17.     } 
  18. /*这是服务器向客户端发送的数据 
  19. (请求行,请求方式:GET;请求的资源路径:/;HTTP协议版本:1.1。) 
  20. GET / HTTP/1.1 
  21. (请求消息头,属性名:属性值) 
  22. Host: 127.0.0.1:8080 
  23. Connection: keep-alive 
  24. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0 
  25. .8 
  26. User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like 
  27. Gecko) Chrome/42.0.2311.152 Safari/537.36 
  28. Accept-Encoding: gzip, deflate, sdch 
  29. Accept-Language: zh-CN,zh;q=0.8 
  30. */ 

HTTP是一个客户端和服务端请求和应答的标准,客户端按照HTTP的标准发送数据到服务端,服务端按照HTTP的标准解析收到的数据。很多软件都内置了此标准。

2. 模拟一个浏览器获取信息。


  1. import java.net.*; 
  2. import java.io.*; 
  3. public class MyBrowser 
  4.         public static void main(String[] args) throws IOException {                 
  5.                 Socket s = new Socket("192.168.1.100",8080); 
  6.                 //模拟浏览器,向tomcat服务端发送符合http协议的请求消息。 
  7.                 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 
  8.                 out.println("GET /myweb/1.html HTTP/1.1"); 
  9.                 out.println("Accept: */*"); 
  10.                 out.println("Host: 192.168.1.100:8080"); 
  11.                 out.println("Connection: close"); 
  12.                 out.println(); 
  13.                 out.println(); 
  14.                 InputStream in = s.getInputStream(); 
  15.                 byte[] buf = new byte[1024]; 
  16.                 int len = in.read(buf); 
  17.                 String str = new String(buf,0,len); 
  18.                 System.out.println(str); 
  19.                 s.close(); 
  20.         } 

HTTP服务端发回的应答消息:

(应答行,HTTP的协议版本:1.1;应答状态码:200;应答状态描述信息:OK。)

HTTP/1.1 200 OK

(应答消息属性信息,属性名:属性值。)

Server: Apache-Coyote/1.1

Accept-Ranges: bytes

ETag: W/"211-1433908112666"

Last-Modified: Wed, 10 Jun 2015 03:48:32 GMT

Content-Type: text/html

Content-Length: 211

Date: Wed, 10 Jun 2015 03:52:16 GMT

Connection: close

应答行中属性名及属性值的具体含义,初学者不用追究,在JavaWeb课程中将会深入讲解。

五、URL和URLConnection类

URI:统一资源标示符。

URL:统一资源定位符,也就是说根据URL能够定位到网络上的某个资源,它是指向互联网“资源”的指针。每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称(URN),它命名资源但不指定如何定位资源。

URL类可以建立到远程对象的连接,也就是说这里面封装了socket,可以直接获取socket流。

1、常用方法


  1. String   getFile();//获取此 URL 的文件名。  
  2. String   getHost();//获取此 URL 的主机名(如果适用)。  
  3. String   getPath();//获取此 URL 的路径部分。  
  4. int      getPort();//获取此 URL 的端口号。  
  5. String   getProtocol();//获取此 URL 的协议名称。  
  6. String   getQuery();//获取此 URL 的查询部分。 
  7. URLConnection   openConnection();//返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 
  8. InputStream   openStream();//打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。此方法是下面方法的缩写:  
  9. openConnection().getInputStream()。 

代码演示:


  1. import java.net.*; 
  2. import java.io.*; 
  3. class  URLConnectionDemo 
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         URL url = new URL("http://192.168.1.254:8080/myweb/demo.html"); 
  7.  
  8.         URLConnection conn = url.openConnection(); 
  9.         System.out.println(conn); 
  10.          
  11.         InputStream in = conn.getInputStream(); 
  12.  
  13.         byte[] buf = new byte[1024]; 
  14.  
  15.         int len = in.read(buf); 
  16.  
  17.         System.out.println(new String(buf,0,len)); 

之所以运行结果中响应头不见了,只能看到主体数据的原因在于:URLConnection对象已经把响应头给解析了。

六、域名解析

在浏览器中输入新浪的域名,DNS解析域名成IP,然后计算机再通过获取到的IP访问新浪服务器。

域名解析,最先走是本地的hosts(C:\WINDOWS\system32\drivers\etc\hosts)文件,解析失败了,才去访问DNS服务器解析、获取IP地址。

可以通过hosts文件可以屏蔽游戏网站内容弹出。

 

作者:金逗逗

来源:51CTO

时间: 2024-09-15 12:25:40

黑马程序员----java基础--网络编程的相关文章

黑马程序员 十一、网络编程

Java帮帮-IT资源分享网  十一.黑马程序员-网络编程 第 11 天:网络编程(1)  1.什么是网络编程? 网络编程的本质是两个设备之间的数据交换,当然,在计算机网络中,设备主要指计算 机.数据传递本身没有多大的难度,不就是把一个设备中的数据发送给两外一个设备,然后 接受另外一个设备反馈的数据.现在的网络编程基本上都是基于请求/响应方式的,也就是 一个设备发送请求数据给另外一个,然后接收另一个设备的反馈.在网络编程中,发起连接 程序,也就是发送第一次请求的程序,被称作客户端(Client)

网络资源-黑马程序员Java 知识——精华总结

获取更多资源Java帮帮IT资源分享网 一.黑马程序员-java 概述与基础知识.................................................................................6 1.何为编程?...................................................................................................................6 2.J

传智播客 黑马程序员JAVA视频分享,0基础到高手的蜕变,不看后悔~~~~

问题描述 全国最顶尖培训机构传智播客的JAVA全套教学视频,一套只要人品不出问题,通过自学就能找到5K工作的视频,我自学也是用的这里面的视频.视频下载链接.拿了视频的,回复一下冒个泡呀~~~ 解决方案 本帖最后由 li413903382 于 2013-02-22 16:09:50 编辑解决方案二:没有人支持么?解决方案三:没有人支持么解决方案四:自己再来支持下解决方案五:支持下你吧,哈俣解决方案六:谢谢分享了,支持哈!!解决方案七:自己来顶了.解决方案八:我觉得不错,对新手而言,非常给力解决方案

黑马程序员--------Java多线程讲解笔记

进程:正在进行中的程序. 每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中一个执行单元或执行情景或执行路径负责进程中程序执行的控制单元 .一个进程中至少要有一个线程.当一个进程中线程有多个时,就是多线程. 为什么要用多线程 1,让计算机"同时"做多件事情,节约时间. 2,后台运行程序,提高程序的运行效率.. 3,多线程可以让程序"同时"处理多个事情. 4,计算机CPU大部分时间处于空闲状态,浪费了CPU资源. 1.创建线程

全国顶尖培训机构黑马程序员JAVA全套教学视频分享

问题描述 大家好,我也是自学派的,只是分享下好的自学视频,自学这套视频,在北京一般找到工作都是5K+如果还想深入的话,还得靠自己继续自学其他扩展提高视频,我只是分享下给大家好东西. 解决方案 解决方案二:在北京5K应该也够呛吧解决方案三:求资源连接我QQ321354544谢谢解决方案四:主公.求资料.QQ:275204149在这先谢谢.

黑马程序员 一、java 概述与基础知识

获取更多资源关注Java帮帮IT资源分享网 一.黑马程序员-java 概述与基础知识 1.何为编程? 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果 的过程. 为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路.方法.和手段通 过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完 成某种特定的任务.这种人和计算机之间交流的过程就是编程.   2.Java 语言概述,历史.特点 是 SUN(Stanford Universit

Java程序员的日常—— 《编程思想》关于类的使用常识

Java虽然利用JVM,让程序员可以放心大胆的使用,可是仍然会出现内存泄露等问题.世上没有绝对的银弹,因此也不能完全把所有的任务都交给JVM,了解Java中的初始化与垃圾回收还是必不可少的知识. 关于构造器 在C中,如果要使用变量需要先申请内存.在Java中,如果你需要创建一个对象,也可以直接new出来,JVM会自动帮你管理. 默认的类,会自动有一个无参的构造方法,当然你也可以自己定义有参的构造方法.但是要注意,一旦自己定义了,就不再帮你自动创建无参的构造方法了. 一个类可以有多种构造方法,通过

Java程序员的日常 —— 《编程思想》包和访问权限

包的作用 在C++中有命名空间的概念,这是因为,不同的项目或者人写出来的代码,可能名称是一样的.比如,java.util中有List,java.awt中也有List,那么我们在开发中,怎么会知道使用的是哪一个List呢? 在Java中是使用包来管理的,比如你可以这样使用: import java.util.ArrayList; java.util.List list = new ArrayList(); 既可以像第一行那样,使用import引用包:也可以直接在Java代码中指定包的路径.一般来说

黑马程序员 九、IO 操作(1)

Java帮帮-IT资源分享网  九.黑马程序员-IO 操作(1) 第九篇 IO 文件操作(1)  1.IO 的概述和 File 方法 IO 流用来处理设备之间的数据传输 Java 对数据的操作是通过流的方式 Java 用于操作流的对象都在 IO 包中 File 类在整个 IO 包中与文件本身有关的操作类,所有的与文件本身有关指的是创建.删除 文件等操作.在 java.io 包中的 File 类本身是一个跨平台的文件操作类,所以在操作中要更 多的考虑到各个操作系统的区别. File 即指文件也指文