目录

网络编程


网络编程

1 网络编程的三个要素

1.1 、IP地址或主机名

  • InetAddress

  • String:192.168.24.71

    • 每一个整数是1~255
  • 域名:www.baidu.com

    • 通过域名解析器,找对对应的ip地址

1.2 、端口号

  • 0~65535

  • 建议不要使用

    • 0~1023

      • 用于基础服务
    • tomcat/jboss

      • 8080
    • mysql

      • 3306
    • oracle

      • 1521
    • sql server

      • 1433
    • 浏览器:http

      • 80
    • ….

1.3 、网络协议

  • OSI理想参考模型

  • TCP/IP的四层实现模式

  • 传输层

    • TCP

      • 面向连接的,可靠的,适用于大数据传输,速率相对低,在传输之前会先“三次握手”,在断开之前会“四次挥手”
    • UDP

      • 非面向连接的,不可靠的,适用于数据比较小的,<=64kb,相对速率高
  • 应用层

    • http/https
    • ftp

2 网络编程的API

2.1 Socket

  • 套接字

    • 表示通信的两个端点,两边各一个
  • 分类

    • 流套接字

      • 用于TCP的通信

        • ServerSocket

          • 转门用于服务器用来监听和接收客户端的连接
        • Socket

          • 用于服务器和客户端的通信
    • 数据报套接字

      • 用于UDP的通信

        • DatagramSocket

          • 用于UDP的两端的通信

2.2 TCP编程步骤

  • 服务器

    • 1、先创建ServerSocket

      • ServerSocket server = new ServerSocket(端口号);

        • 指定端口号进行监听,客户端通过这个端口号与它进行连接和通信
    • 2、接收客户端的连接

      • Socket socket = server.accept();

        • 每一个客户端就要有自己的一个Socket
        • 如果希望不同的客户端通信“同时”进行,需要每一个socket用一个线程进行维护
    • 3、通过socket进行收或发消息

      • 收消息

        • InputStream is = socket.getInputStream();

          • 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
      • 发消息

        • OutputStream out = socket.getOutputStream();

          • 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
    • 4、与客户端断开连接

      • socket.close();
  • 客户端

    • 1、先与服务器建立连接,通过创建一个Socket,要指定服务器的IP和端口号

      • Socket socket = new Socket(服务器的IP,服务器的监听端口号);
    • 2、通过socket进行收或发消息

      • 收消息

        • InputStream is = socket.getInputStream();

          • 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
      • 发消息

        • OutputStream out = socket.getOutputStream();

          • 可以在此基础上,包装缓冲流,转换流,对象流,打印流,数据流等
      • 收和发可以用不同的线程进行维护

    • 3、与客户端断开连接

      • socket.close();
  • 示例一

    package com.atguigu.tcp1;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.net.ServerSocket;

    import java.net.Socket;

    import org.junit.Test;

    /*

    • TCP:面向连接

    • 通信的两端分角色:服务器端和客户端

  • 服务器端等着被连接,客户端主动连接

  • 服务器端:

  • 1、ServerSocket:用来接收客户端的连接信息

  • 2、Socket:用来与某个客户端进行通信

  • 客户端:

  • 1、Socket:用来与服务器进行通信

*/

public class TestTCP1 {

@Test

public void server()throws Exception{

	//1、创建ServerSocket,看成:开启服务器 ,需要指定一个端口号,监听是否有客户端来连接

	ServerSocket ss = new ServerSocket(9090);



	while(true){

		System.out.println("等待您的链接....");

		//2、等待客户端的连接,接收客户端的连接(如果没有人连接,那么这句代码会阻塞)

		//一旦有客户端连接成功,那么就会产生一个Socket对象,专门负责和这个客户端通信

		Socket socket = ss.accept();



		System.out.println(socket.getInetAddress().getHostAddress()+"连接成功");



		//3、可以接收消息,或发生消息

		//例如:先发:“欢迎登陆”

		//在接收消息



		//发消息:输出流,OutputStream

		OutputStream output = socket.getOutputStream();

		output.write("欢迎登陆".getBytes());

		socket.shutdownOutput();



		//收消息

		InputStream is = socket.getInputStream();



		byte[] data = new byte[1024];

		int len;

		StringBuilder sb = new StringBuilder();

		while((len= is.read(data)) !=-1){

			sb.append(new String(data,0,len));

		}

		System.out.println("服务器收到的消息:" + sb);



		//4、关闭连接

		socket.close();//只是与某个客户端断开

	}



	//5、服务器关闭

// ss.close();

}



@Test

public void client()throws Exception{

	//1、创建一个Socket,要指定服务器的IP和端口号

	Socket socket = new Socket("192.168.24.71",9090);



	//2、接收消息

	InputStream is = socket.getInputStream();



	byte[] data = new byte[1024];

	int len;

	StringBuilder sb = new StringBuilder();

	while((len= is.read(data)) !=-1){

		sb.append(new String(data,0,len));

	}

	System.out.println("客户端收到的消息:" + sb);



	//3、发送消息

	String info = "马上吃饭了";

	OutputStream out = socket.getOutputStream();

	out.write(info.getBytes());



	//3、关闭连接

	socket.close();

}

}

  • 示例二

    package com.atguigu.tcp2;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.io.OutputStream;

    import java.net.ServerSocket;

    import java.net.Socket;

    import java.util.Scanner;

    import org.junit.Test;

    public class TestTCP2 {

    @Test

    public void server()throws Exception{

      //1、创建ServerSocket
    
      ServerSocket server = new ServerSocket(9999);
    
    
    
      while(true){
    
      	//2、等待客户端的连接,接收客户端的连接
    
      	Socket socket = server.accept();
    
      	String clientIp = socket.getInetAddress().getHostAddress();
    
    
    
      	System.out.println(clientIp+"上线了");
    
    
    
      	//每一个客户端需要一个线程单独维护它的通信,“同时”与服务器通信的效果
    
      	new MessageHandler(socket).start();
    
      }
    

    }

    //和服务器连接上以后,从键盘输入消息,给服务器发送,一直到从键盘输入byebye,在与服务端口连接

    @Test

    public void client()throws Exception{

      //1、连接服务器
    
      Socket socket = new Socket("192.168.24.71",9999);
    
    
    
      OutputStream out = socket.getOutputStream();
    
    
    
      //2,从键盘输入给服务器发送
    
      Scanner input = new Scanner(System.in);
    
      while(true){
    
      	System.out.println("输入要发送的内容:");
    
      	String info = input.nextLine();
    
    
    
      	if("byebye".equals(info)){
    
      		break;
    
      	}
    
    
    
      	//给服务器发送
    
      	out.write((info+"\n").getBytes());
    
      }
    
    
    
      //3、断开
    
      socket.close();
    

    }

    }

    class MessageHandler extends Thread{

    private Socket socket;

    public MessageHandler(Socket socket) {

      super();
    
      this.socket = socket;
    

    }

    public void run(){

      try {
    
      	//3、和一个客户端多次通信,接收到消息后,在控制台打印
    
      	InputStream input = socket.getInputStream();
    
      	InputStreamReader isr = new InputStreamReader(input);
    
      	BufferedReader br = new BufferedReader(isr);
    
    
    
      	String str;
    
      	while((str = br.readLine())!=null){
    
      		System.out.println(socket.getInetAddress().getHostAddress() +"说:"+ str);
    
      	}
    
    
    
      	//4、断开
    
      	socket.close();
    
      } catch (IOException e) {
    
      	e.printStackTrace();
    
      }
    

    }

    }

  • 示例三:群聊

    • 服务器

      package com.atguigu.tcp2;

      import java.io.BufferedReader;

      import java.io.IOException;

      import java.io.InputStream;

      import java.io.InputStreamReader;

      import java.io.OutputStream;

      import java.net.ServerSocket;

      import java.net.Socket;

      import java.util.Scanner;

      import org.junit.Test;

      public class TestTCP2 {

      @Test

      public void server()throws Exception{

        //1、创建ServerSocket
      
        ServerSocket server = new ServerSocket(9999);
      
      
      
        while(true){
      
        	//2、等待客户端的连接,接收客户端的连接
      
        	Socket socket = server.accept();
      
        	String clientIp = socket.getInetAddress().getHostAddress();
      
      
      
        	System.out.println(clientIp+"上线了");
      
      
      
        	//每一个客户端需要一个线程单独维护它的通信,“同时”与服务器通信的效果
      
        	new MessageHandler(socket).start();
      
        }
      

      }

      //和服务器连接上以后,从键盘输入消息,给服务器发送,一直到从键盘输入byebye,在与服务端口连接

      @Test

      public void client()throws Exception{

        //1、连接服务器
      
        Socket socket = new Socket("192.168.24.71",9999);
      
      
      
        OutputStream out = socket.getOutputStream();
      
      
      
        //2,从键盘输入给服务器发送
      
        Scanner input = new Scanner(System.in);
      
        while(true){
      
        	System.out.println("输入要发送的内容:");
      
        	String info = input.nextLine();
      
      
      
        	if("byebye".equals(info)){
      
        		break;
      
        	}
      
      
      
        	//给服务器发送
      
        	out.write((info+"\n").getBytes());
      
        }
      
      
      
        //3、断开
      
        socket.close();
      

      }

      }

      class MessageHandler extends Thread{

      private Socket socket;

      public MessageHandler(Socket socket) {

        super();
      
        this.socket = socket;
      

      }

      public void run(){

        try {
      
        	//3、和一个客户端多次通信,接收到消息后,在控制台打印
      
        	InputStream input = socket.getInputStream();
      
        	InputStreamReader isr = new InputStreamReader(input);
      
        	BufferedReader br = new BufferedReader(isr);
      
      
      
        	String str;
      
        	while((str = br.readLine())!=null){
      
        		System.out.println(socket.getInetAddress().getHostAddress() +"说:"+ str);
      
        	}
      
      
      
        	//4、断开
      
        	socket.close();
      
        } catch (IOException e) {
      
        	e.printStackTrace();
      
        }
      

      }

      }

    • 客户端

      package com.atguigu.tcp3;

      import java.io.BufferedReader;

      import java.io.IOException;

      import java.io.InputStream;

      import java.io.InputStreamReader;

      import java.io.OutputStream;

      import java.io.PrintStream;

      import java.net.Socket;

      import java.net.SocketException;

      import java.util.Scanner;

      /*

   */

  public class TestTCPClient{

  	public static void main(String[] args) throws Exception{

  		//1、连接服务器

  		Socket socket = new Socket("192.168.24.71",9090);



  		//2、创建两个线程,一个收,一个发

  		SendThread send = new SendThread(socket);

  		send.start();

  		RecevierThread r = new RecevierThread(socket);

  		r.start();



  		send.join();



  		r.setExit(true);



  		//3、关闭

  		socket.close();

  	}

  }

  class SendThread extends Thread{

  	private Socket socket;



  	public SendThread(Socket socket) {

  		super();

  		this.socket = socket;

  	}



  	@Override

  	public void run() {

  		try {

  			OutputStream output = socket.getOutputStream();

  			PrintStream ps = new PrintStream(output);



  			Scanner input = new Scanner(System.in);

  			while(true){

  				System.out.println("请输入要发送的内容:");

  				String info = input.nextLine();

  				if("bye".equals(info)){

  					break;

  				}

  				//给服务器发送

  				ps.println(info);

  			}



  		} catch (IOException e) {

  			e.printStackTrace();

  		}

  	}

  }

  class RecevierThread extends Thread{

  	private Socket socket;

  	private boolean exit = false;



  	public RecevierThread(Socket socket) {

  		super();

  		this.socket = socket;

  	}

  	@Override

  	public void run() {

  		try {

  			InputStream is = socket.getInputStream();

  			InputStreamReader isr = new InputStreamReader(is);

  			BufferedReader br = new BufferedReader(isr);



  			String str;

  			while(exit==false){

  				try {

  					str = br.readLine();

  				} catch (SocketException e) {

  					break;

  				}

  				if(str==null){

  					break;

  				}

  				System.out.println("收到的消息:" + str);

  			}



  		} catch (IOException e) {

  			e.printStackTrace();

  		}

  	}

  	public void setExit(boolean exit) {

  		this.exit = exit;

  	}



  }

2.3 UDP编程步骤

  • 发送端

    • 1、创建一个DatagramSocket

    • 2、准备发送的数据,并且打包

      • DatagramPacket

        • 要指定:发送的数据,长度,接收方的IP,接收方的端口号
    • 3、通过DatagramSocket的send(数据报)

    • 4、关闭

  • 接收端

    • 1、创建一个DatagramSocket

      • 要指定 监听的端口号
    • 2、准备一个DatagramPacket,用来接收数据

      • 要指定装数据一个字节数组,以及长度
    • 3、通过DatagramSocket的receive(数据报)

    • 4、拆解数据

      • 通过DatagramPacket对象.getData()数据,DatagramPacket对象.getLength()实际接收的数据长度
    • 5、关闭

  • 示例代码

    package com.atguigu.udp;

    import java.net.DatagramPacket;

    import java.net.DatagramSocket;

    import java.net.InetAddress;

    import org.junit.Test;

    /*

    • UDP:非面向连接的

  • 有发送端和接收端两个应用程序

*/

public class TestUDP {

@Test

public void send()throws Exception{

	//1、创建Socket

	DatagramSocket ds = new DatagramSocket();



	//2、把数据打包成一个数据报,包

	String str = "双十二购物快乐";

	byte[] bytes = str.getBytes();

	InetAddress ip = InetAddress.getByName("192.168.24.71");

	DatagramPacket dp = new DatagramPacket(bytes, bytes.length, ip,8989);



	//3、通过socket发送出去

	ds.send(dp);

	System.out.println("发送完毕");



	//4、释放资源

	ds.close();

}



@Test

public void reveive()throws Exception{

	//1、创建Socket

	DatagramSocket ds = new DatagramSocket(8989);//为它指定一个端口号,在端口号一直监听着



	//2、先创建一个数据报等着

	byte[] data = new byte[1024];

	DatagramPacket dp  = new DatagramPacket(data, data.length);



	//3、准备接受数据,从socket中接收数据,如果此时没有数据,这句代码会阻塞

	ds.receive(dp);



	//4、拆出数据

	String str = new String(dp.getData(),0,dp.getLength());

	System.out.println("收到的数据是:" + str);



	//5、关闭

	ds.close();

}

}

2.4 URL编程

  • 在TCP的基础上

    • 服务器端

      • Web服务器
    • 客户端

      • 1、创建URL的对象

        • URL url = new URL(网址);

          • 网址:协议://主机名:端口号/文件路径名?参数名=参数值&参数名=参数值…
          • 例如:http://localhost:8080/1108web/index.html
          • 例如:http://localhost:8080/1108web/login?username=xx&password=xx
      • 2、与服务器建立连接

        • InputStream is = url.openStream();

          • 这种方式只能使用get方法与服务器进行通信

            • 如果要给服务器传参数只能在网址后面通过?参数名=参数值&参数名=参数值…
        • HttpURLConnection tc = (HttpURLConnection)url.openConnection();

          • 这种方式可以使用post方法与服务器进行通信

            • 如果要给服务器传数据,那么需要hc.setDoOutput(true);
            • 然后用OutputStream进行发送数据
      • 3、处理接收到数据

  • 示例代码

    • 示例一

      package com.atguigu.url;

      import java.io.BufferedReader;

      import java.io.InputStream;

      import java.io.InputStreamReader;

      import java.net.URL;

      /*

      • tomcat:是一个服务器

      • 浏览器:客户端

      */

      public class TestURL {

      public static void main(String[] args) throws Exception{

        //自定义客户端
      
      
      
        URL url = new URL("http://192.168.24.71:8080/1108JavaWeb/index.html");
      
        /*System.out.println("协议:" + url.getProtocol());
      
        System.out.println("主机名:" + url.getHost());
      
        System.out.println("端口号:" + url.getPort());
      
        System.out.println("路径名:" + url.getPath());*/
      
      
      
        InputStream input = url.openStream();
      
        InputStreamReader isr = new InputStreamReader(input);
      
        BufferedReader br  = new BufferedReader(isr);
      
      
      
        String str ;
      
        while((str=br.readLine())!=null){
      
        	System.out.println(str);
      
        }
      

      }

      }

    • 示例二:get

      package com.atguigu.url;

      import java.io.BufferedReader;

      import java.io.InputStream;

      import java.io.InputStreamReader;

      import java.net.URL;

      public class TestURL2 {

      public static void main(String[] args) throws Exception{

        URL url = new URL("http://192.168.24.71:8080/myweb/login?username=admin&pass=123");
      
        InputStream input = url.openStream();
      
        InputStreamReader isr = new InputStreamReader(input);
      
        BufferedReader br  = new BufferedReader(isr);
      
      
      
        String str ;
      
        while((str=br.readLine())!=null){
      
        	System.out.println(str);
      
        }
      

      }

      }

    • 示例三:post

      package com.atguigu.url;

      import java.io.BufferedReader;

      import java.io.InputStream;

      import java.io.InputStreamReader;

      import java.io.OutputStream;

      import java.io.PrintStream;

      import java.net.HttpURLConnection;

      import java.net.URL;

      public class TestURL3 {

      public static void main(String[] args) throws Exception{

        URL url = new URL("http://192.168.24.71:8080/myweb/login");
      
      
      
        HttpURLConnection hc = (HttpURLConnection) url.openConnection();
      
      
      
        hc.setDoOutput(true);
      
        OutputStream output = hc.getOutputStream();
      
        PrintStream ps = new PrintStream(output);
      

      // output.write(“username=chai&pass=123”.getBytes());

        ps.println("username=chai&pass=123");
      
      
      
        InputStream input = hc.getInputStream();
      
        InputStreamReader isr = new InputStreamReader(input);
      
        BufferedReader br  = new BufferedReader(isr);
      
      
      
        String str ;
      
        while((str=br.readLine())!=null){
      
        	System.out.println(str);
      
        }
      

      }

      }