java入门基础(十一)


一、网络编程

  • 概述:在通信协议下,实现不同计算机之间可以进行数据互换,实现资源共享和信息传递的计算机系统。
  • 三要素
    • IP地址:设备在网络中的唯一标识,在网络中计算机能够互相通信,必须通过IP地址这个标识来指定要接收的计算机和识别发送的计算机
    • 端口:网络通信,本质就是两个应用之间的通信,每台计算机中都有很多的应用程序,端口号就是为了区分这些应用程序,如果说IP地址是计算机在网络中的而唯一标识,端口号就是应用在计算机中的唯一标识
    • 网络通信协议:在多台计算机之间进行数据传输,必须要遵循一定的规则,这些规则被称为网络通信协议,它对传输格式,传输速率,传输步骤做了一定的统一,通信双方必须同时遵守才能发生数据交换,常见的协议有UDP和TCP协议

二、IP地址

  • 网络中的唯一标识,同一台主机,不同的网络条件下,IP地址不同

  • 分类:

    • ipv4(常用) :32bit 4字节
    • ipv6:128bit 16字节
  • java中获取IP地址的方法
    Java通了一个类InetAddress,使用这个类来操作IP地址
    InetAddress:此类表示Internet协议(IP)地址,该类没有构造方法,但是变量名和方法名大多是static修饰,可以通过类名直接调用。
    在这里插入图片描述

代码演示

public class Test {
    
    
    public static void main(String[] args)throws Exception {
    
    
        InetAddress ip=InetAddress.getByName("192.168.0.34");//此处也可以给主机名
        System.out.println(ip.getHostAddress());
        System.out.println(ip.getHostName());
        System.out.println(ip);
        System.out.println("=================");
        InetAddress ip1=InetAddress.getByName("WIN-LCLL0FAUL50");
        System.out.println(ip1.getHostName());
        System.out.println(ip1);
        System.out.println(ip1.getHostAddress());

    }
}

在这里插入图片描述

三、端口号

  • 设备上应用的唯一标识,使用端口号时,要注意端口号被占用的问题
  • 可以通过自己指定的端口号,用于通信,类型为int型

四、网络通信协议

  • 设备中连接和通信的规则被称为网络通信协议

(一)UDP协议:用户数据协议

  • 是一种无连接通讯协议,即在数据传输,发送端和接收端不会建立连接,也就是当发送端发送一条数据时,发送端不会确定接收端是否存在,就会发送数据,同样,接收端在接收到数据时,也不会向发送端反馈是否接收到数据
  • 例如:邮差送信,他只管送信,不管有没有人接收到
  • UDP协议由于是无连接性,可能会有数据丢失的情况,不能保证数据的完整性,因此在传输重要数据时不建议使用
  • UDP是不可靠的网络通信,在通信两端个建立一个Socket对象,
    但是两个Socket只是发送数据,接收数据的对象

1.UDP发送数据

  • 创建发送端的Scoket对象(DatagramSocket),单向发送时,不需要指定自己的端口号。
  • 创建数据,并把数据打包
  • 调用DatagramPacket方法send()发送数据
  • 关闭发送端close()

2.UDP接收数据

  • 创建接收端的Scoket对象(DatagramSocket),需指定自己的端口号,用于接收数据
  • 创建数据包,用于接收数据
  • 调用Scoket对象(DatagramSocket)receice()方法接收数据
  • 解析数据包,在控制台显示 getData() getLength()
  • 关闭接收端

代码演示:
发送方:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Send {
    
    
    public static void main(String[] args)throws Exception {
    
    
        DatagramSocket ds=new DatagramSocket();

        InetAddress ip=InetAddress.getByName("192.168.0.37");
        int port =1023;

        byte[] bytes="hello".getBytes();
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length,ip,port);
        ds.send(dp);
        ds.close();
        }
 }

数据发送后,程序结束,不管对方有没有收到
在这里插入图片描述

接收方:

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receive {
    
    
    public static void main(String[] args) throws Exception{
    
    
        DatagramSocket ds=new DatagramSocket(1023);

        byte[] bytes = new byte[1024];
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length);

        ds.receive(dp);

        byte[] b=dp.getData();
        System.out.println(new String(b,0,b.length));
        ds.close();
    }
}

接收不到数据,程序不停止,一般先运行接收方,等待接收数据,再运行发送方,发送数据。接收方接到数据,程序停止。
在这里插入图片描述
在这里插入图片描述
双向通信代码演示,输入bye通信停止
发送方:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Send {
    
    
    public static void main(String[] args) throws Exception{
    
    
        DatagramSocket ps=new DatagramSocket(1234);

        InetAddress ip=InetAddress.getByName("192.168.0.37");
        int port=1235;
        Scanner sc=new Scanner(System.in);
        while (true){
    
    
            System.out.println("请输入要发送的数据");
            String string=sc.nextLine();
            byte[] byte1=string.getBytes();
            DatagramPacket dp=new DatagramPacket(byte1,byte1.length,ip,port);
            ps.send(dp);
            if(string.equals("bye")){
    
    
                break;
            }

            byte[] byte2 = new byte[1024];
            DatagramPacket dp1=new DatagramPacket(byte2,byte2.length);
            ps.receive(dp1);
            String s=new String(dp1.getData(),0,dp1.getLength());
            if(s.equals("bye")){
    
    
                System.out.println("接收到bye,通信结束");
                break;
            }
            System.out.println("成功接收到"+s);

        }
        ps.close();
    }
}

接收方的代码块


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Receive {
    
    
    public static void main(String[] args)throws Exception {
    
    
        DatagramSocket ps=new DatagramSocket(1235);

        InetAddress ip=InetAddress.getByName("192.168.0.37");
        int port=1234;
        Scanner sc=new Scanner(System.in);
        while(true){
    
    
            byte[] byte1 = new byte[1024];
            DatagramPacket dp1=new DatagramPacket(byte1,byte1.length);
            ps.receive(dp1);
            String string1=new String(dp1.getData(),0,dp1.getLength());
            if(string1.equals("bye")){
    
    
                System.out.println("接收到bye,通信结束");
                break;
            }
            long l = System.currentTimeMillis();
            Date date = new Date();
            SimpleDateFormat s = new SimpleDateFormat("yyyy:MM:dd,HH:mm:ss");
            System.out.println(s.format(date)+"   成功接收   \n"+string1);

            System.out.println("请输入要发送的数据");
            String string2=sc.nextLine();
            byte[] byte2=string2.getBytes();
            DatagramPacket dp2=new DatagramPacket(byte2,byte2.length,ip,port);
            ps.send(dp2);
            if(string2.equals("bye")){
    
    
                break;
            }
        }
        ps.close();
    }
}

在这里插入图片描述
在这里插入图片描述

(二)TCP协议:传输控制协议

  • TCP协议是面向连接协议,即数据传输之前,客户端和服务端会建立连接,然后在进行数据传输,提供了可靠无差错的数据传输,每次连接都要进行三次“握手”原则
  • 三次“握手”原则:建立连接时,客户端和服务端会进行三次交互
    第一次:客户端向服务端发送连接请求,等待服务端响应
    第二次:服务端向客户端返回一个响应,通知客户端收到了连接请求
    第三次:客户端向服务端发送确认消息,建立连接
  • Java对基于TCP协议的网络提供了良好的封装,使用Socket对象老代表两端的通信端口,并通过Socket产生IO流进行网络通信
  • Java为客户端提供了Socket类,服务器端提供了ServerSocket类

1.TCP客户端发送数据

  • 1.创建客户端的Socket对象
    new Socket(String host,int port);
  • 2.创建输出流,写数据
    getOutputStream();
  • 3.关释放资源
    close()

2.TCP服务器端接收数据

  • 1.创建客户端的Socket对象(ServerSocket)
    new ServerSocket(int port);
  • 2.调用ServerSocket监听端口号,接收数据
    accept();
  • 3.创建输入流,读数据
    getInputStream();
    read();
  • 4.解析数据,并在控制台显示
    new String(byte[] byte, int off,int length)
  • 5.关释放资源
    close()

代码演示
客户端:

import java.io.OutputStream;
import java.net.Socket;

public class Cilent {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket = new Socket("192.168.0.37", 1236);
        OutputStream os = socket.getOutputStream();
        for(int i=1;i<6;i++) {
    
    
            os.write(("数据"+i).getBytes());
        }
        socket.close();
    }
}

服务器端:

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    
    
    public static void main(String[] args) throws Exception {
    
    
        ServerSocket ss = new ServerSocket(1236);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1) {
    
    
            System.out.print(new String(bytes, 0, len));
        }
        socket.close();
    }
}

结果:注意运行的时候要先运行服务器端
服务器端
在这里插入图片描述
客户端:
在这里插入图片描述
但是在双向传输的时候会出现阻塞问题,需加上shutOutputdown()方法。或者无法实现双向传输。

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Cilent {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket = new Socket("192.168.0.37", 1236);
        OutputStream os = socket.getOutputStream();
        for(int i=1;i<6;i++) {
    
    
            os.write(("数据"+i).getBytes());
        }
        socket.shutdownOutput();

        InputStream ip=socket.getInputStream();
        int len;
        byte[] bytes = new byte[1024];
        while ((len=ip.read(bytes))!=-1){
    
    
            System.out.println(new String(bytes,0,len));
        }
        socket.close();
    }
}
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    
    
    public static void main(String[] args) throws Exception {
    
    
        ServerSocket ss = new ServerSocket(1236);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1) {
    
    
            System.out.print(new String(bytes, 0, len));
        }

        OutputStream os=socket.getOutputStream();
        os.write("我爱java".getBytes());
        socket.shutdownOutput();
        os.flush();
        socket.close();
    }
}

在这里插入图片描述
在这里插入图片描述

  • 一次双向传输中会遇到阻塞使用shutOutputdown方法解决,但是多次循环双向中就不能使用这个方法,为了解决这个问题,我们使用简答高效的字符缓冲流,通过字符缓冲流 还可以解决中文读取不完整的情况 BufferedReader
  • 字符缓冲流中有读取行的readLine(),newLine( )方法简单高效,还是会出现阻塞,但是除了shutoutputdown方法外,可以使用不循环读取ReadLine的方法,并且该方法可以解决循环双向通信的问题。

3.解决阻塞的方法

案例1客户端发给服务器端,服务器告知客户端收到数据,双向通信

出现阻塞的代码

客户端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class Cilent {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket=new Socket("192.168.0.37",1800);
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s=scanner.next();
        bw.write(s);
        bw.flush();//必须加

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s1;
        while ((s1=br.readLine())!=null){
    
    
            System.out.println(new String(s1));
        }
        socket.close();
    }
}

服务器端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Sever {
    
    
    public static void main(String[] args)throws Exception {
    
    
        ServerSocket ss=new ServerSocket(1800);
        Socket socket=ss.accept();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s;
        while ((s=br.readLine())!=null){
    
    
            System.out.println(new String(s));
        }

        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s1=scanner.next();
        bw.write(s1);
        bw.flush();//必须加
        ss.close();
    }

}

运行结果:
在这里插入图片描述
在这里插入图片描述

客户端和服务器端都产生阻塞,程序无法继续运行,也不停止

解决方法一:socket.shutdownOutput()

  • 在写入流后面加上socket.shutdownOutput();告知不再有数据要写入
    客户端:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class Cilent {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket=new Socket("192.168.0.37",1800);
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s=scanner.next();
        bw.write(s);
        bw.flush();//必须加
        socket.shutdownOutput();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s1;
        while ((s1=br.readLine())!=null){
    
    
            System.out.println(new String(s1));
        }
        socket.close();
    }
}

服务器端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Sever {
    
    
    public static void main(String[] args)throws Exception {
    
    
        ServerSocket ss=new ServerSocket(1800);
        Socket socket=ss.accept();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s;
        while ((s=br.readLine())!=null){
    
    
            System.out.println(new String(s));
        }

        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s1=scanner.next();
        bw.write(s1);
        bw.flush();//必须加
        ss.close();
        socket.shutdownOutput();

    }

}

结果
在这里插入图片描述
在这里插入图片描述
注意:输入的字符串中不能有空格,输完之后要按回车,表示输入结束。

解决方法二:写入不循环读取ReadLine

  • 约定两边的数据大小(数据传递时,最大的数据量),避免使用循环读取

客户端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class Cilent {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket=new Socket("192.168.0.37",1800);
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s=scanner.next();
        bw.write(s+"\n");
        bw.flush();//必须加

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s1=br.readLine();
        System.out.println(s1);
        socket.close();
    }
}

服务器端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Sever {
    
    
    public static void main(String[] args)throws Exception {
    
    
        ServerSocket ss=new ServerSocket(1800);
        Socket socket=ss.accept();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s=br.readLine();
        System.out.println(s);

        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner=new Scanner(System.in);
        String s1=scanner.next();
        bw.write(s1+"\n");
        bw.flush();//必须加
        ss.close();

    }

}

在这里插入图片描述
在这里插入图片描述
注意:输入的字符串中不能有空格,输入完成后按回车

对于聊天、循环多次传输数据只能使用方法二

代码演示
客户端:

//问题一:服务器端读不到数据,控制台不显示,即阻塞
//解决方法一,如果不是聊天或者多次来回,用socket调用shutoutputdown
//解决方法二,是聊天的话,在每次写入数据的时候,写个换行,可以写入一个newLine,也可以直接写一个换行符, 服务器端按行读取
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class ClientTest {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Socket socket=new Socket("192.168.0.37",1027);
        System.out.println();
        while(true) {
    
    
            //发送数据
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            Scanner scanner=new Scanner(System.in);
            String string=scanner.next();//注意写入得数据中不能有空格
            bw.write(string);
            bw.newLine();
            bw.flush();//必须刷新一下
            if(string.equals("bye")){
    
    
                break;
            }

            BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String s=br.readLine();
            System.out.println(" 客户端收到的数据为: "+s);
            if(s.equals("bye")){
    
    
                System.out.println("通信结束");
                break;
            }
        }
        socket.close();
    }
}

服务器端;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class ServerTest {
    
    
    public static void main(String[] args)throws Exception {
    
    
        ServerSocket ss=new ServerSocket(1027);
        Socket socket=ss.accept();
        while (true){
    
    
            BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String s= br.readLine();

            long l=System.currentTimeMillis();
            Date date=new Date();
            SimpleDateFormat s1 =new SimpleDateFormat("yyyy:mm:dd,hh:mm:ss");
            System.out.print(s1.format(date));

            System.out.println(" 服务器端收到的数据为: "+s);
            if(s.equals("bye")){
    
    
                System.out.println("通信结束");
                break;
            }

            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            Scanner scanner=new Scanner(System.in);
            String string=scanner.next();
            bw.write(string+"\n");
            bw.flush();
            if(string.equals("bye")){
    
    
                break;
            }
        }
        ss.close();
    }
}

在这里插入图片描述
在这里插入图片描述

五、总结

什么是网络编程:多台设备之间进行数据传输
网络编程三要素:IP地址  端口  网络通信协议
	IP地址:是设备在网络中的唯一标识
	端口:是应用在设备中的唯一标识
	网络通信协议:多台设备之间进行数据传输所要遵循的规则(传输格式,传输速率...),常见的网络通信协议有UDP和TCP
	注意:IP地址在不同的网络是会发生变化的,电脑的唯一标识是MAC地址
	Java中如何使用IP地址:Java提供了InetAddress来进行操作
		static InetAddress getByName(String host)	确定主机名称的IP地址,主机名称可以是机器名称,也可以是Ip地址
		String getHostName()	获取此IP地址的主机名
		String getHostAddress()	返回IP地址的字符串
UDP:无连接通信协议,不能保证数据的安全性
	发送端:
		1.创建端点new DataGramSocket();
		2.创建包并发送数据
			"nihao".getBytes();
			new DataGramPacket(bytes,bytes.length,ip,port);
		3.发送数据,调用DataGramSocket中的send(DataGramPacket dp);
		4.关闭
	接收端:	
		1.创建端点new DataGramSocket(port);
		2.创建包
			new byte[1024];
			new DataGramPacket(bytes,bytes.length);
		3.接收数据,调用DataGramSocket中的receive(DataGramPacket dp);
		4.解析数据
			new String(dp.getData(),0,dp.getLenght());
		5.关闭
TCP:面对连接通讯协议,能保证数据的安全性,通过三次握手建立连接
	三次握手
		第一次:客户端向服务端发送连接请求,等待响应
		第二次:服务端响应请求,向客户端发送,可以创建连接的请求
		第三次:客户端向服务端建立网络虚拟链路(连接通道)
	客户端:
		1.创建端点Socket socket=new Socket(ip,port);
		2.创建流 socket.getOutputStream();
		3.写数据
		4.关闭
	服务端:
		1.创建端点ServerSocket ss=new ServerSocket(port);
		2.监听端口 Socket socket=ss.accept();
		3.创建流 socket.getInputStream
		4.接收数据
		5.关闭
注意:1.监听端口号,就是监听这个端口有没有数据进行传输
       2.阻塞问题:接收数据时,没有办法判断什么时候接受结束,然后一直在接受
     	解决方式1:shutdownOutPut()	不适用于聊天
     	解决方式2:约定两边的数据大小(数据传递时,最大的数据量),避免使用循环读取

六、习题

(一)填空题

1. _____Ip地址______用来标志网络中的一个通信实体的地址。通信实体可
以是计算机,路由器等。 

2.统一资源定位符URL是指向互联网“资源”的指针,由4部分组成:协议、存放
资源的主机域名、____端口______和资源路径和文件名。

3. URL __       是统一资源定位器的简称,它表示Internet上某一资源的地址。

4.在Socket编程中,IP地址用来标志一台计算机,但是一台计算机上可能提
供多种应用程序,使用   _端口         来区分这些应用程序。

5.在Java Socket网络编程中,开发基于TCP协议的服务器端程序使用的套接
字是  __ServerSocket         。

6.在Java Socket网络编程中,开发基于UDP协议的程序使用的套接字是 
_DatagramSocket_        。

(二)选择题

1.	以下协议都属于TCP/IP协议栈,其中位于传输层的协议是(   AD  )。(选择二项)
		
	A	TCP
	B.	HTTP
	C.	SMTP
	D.	UDP

2.	以下协议中属于TCP/IP协议栈中应用层协议的是(  A   )。(选择一项)
		
	A	HTTP
	B.	TCP
	C.	UDP
	D.	IP

3.	以下说法中关于UDP协议的说法正确的是(  A D  )。(选择二项)
		
	A.	发送不管对方是否准备好,接收方收到也不确认
	B.	面向连接
	C.	占用系统资源多、效率低
	D.	非常简单的协议,可以广播发送

4.	在基于TCP网络通信模式中,客户与服务器程序的主要任务是(  BC  )。(选择二项)
		
	A	客户程序在网络上找到一条到达服务器的路由
	B.	客户程序发送请求,并接收服务器的响应
	C.	服务器程序接收并处理客户请求,然后向客户发送响应结果
	D.	如果客户程序和服务器都会保证发送的数据不会在传输途中丢失


5.	在Java网络编程中,使用客户端套接字Socket创建对象时,需要指定(  A )。(选择一项)
		
	A	服务器主机名称和端口
	B.	服务器端口和文件
	C.	服务器名称和文件
	D.	服务器地址和文件

6.	ServerSocket的监听方法accept( )方法的返回值类型是(  A  )。(选择一项)
		
	A.	Socket
	B.	void
	C.	Object
	D.	DatagramSocket

7.	Java UDP Socket编程主要用到的两个类是(   BD  )。(选择二项)
		
	A	UDPSocket
	B.	DatagramSocket
	C.	UDPPacket
	D.	DatagramPacket

8.	在使用UDP套接字通信时,常用(  D  )类把要发送的信息打包。(选择一项)
		
	A	String
	B.	DatagramSocket
	C.	MulticastSocket
	D.	DatagramPacket

(三)判断题

1.Socket是传输层供给应用层的编程接口,是应用层与传输层之间的桥梁 。(   T )

2.TCP/IP传输控制协议是Internet的主要协议,定义了计算机和外设进行通信
的规则。TCP/IP网络参考模型包括七个层次:应用层、会话层、表示层、传
输层、网络层、链路层和物理层。(  X   )

3.TCP协议一种面向连接的、可靠的、基于字节流的通信协议 。HTTP、
FTP、TELNET、SMTP 都是基于TCP协议的应用层协议。(   T )

4.UDP协议是一种面向无连接的、可靠的、基于字节流的传输层通信协议,
该协议占用系统资源多、效率较低。(  X  )

(四)简答题

1.TCP/IP协议栈中,TCP协议和UDP协议的联系和区别?
答:
TCP:优点:
1、面向连接的传输;
2、数据传输稳定可靠;
3、端到端的通信;
4、全双工方式;
5、以字节为单位传输
缺点:传输速度不够快

UDP:DP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去,每个数据包的大小限定在64K以内!
优点:1、传输速度快;2、效率高;
缺点:数据包可能会丢失

TCP协议和UDP协议各有所长、各有所短,适用于不同要求的通信环境。

2.简述基于TCP的Socket编程的主要步骤。
提示:分别说明服务器端和客户端的编程步骤。
服务器端:
1)创建Servrsocket实例指定本地端口
2)调用accept()获得链接请求,建立连接。
3)通过返回的socket实例调用getOutputStream和getInputStream读写数据
4)结束时调用socket实例的close关闭连接。
客户端:
1)创建socket实例,指定远程服务器地址和端口
2)socket实例调用getOutputStream和getInputStream读写数据
3)关闭连接

3.简述基于UDP的Socket编程的主要步骤。
提示:分别说明服务器端和客户端的编程步骤。
客户端:
1)建立DatagramSocket指定本地端口。
2)建立DatagramPacket(byte,byte.length,ip,port)数据包
3)调用DatagramSocket的send方法,发送数据包
4)调用DatagramSocket的close方法,关闭
服务器端:
1)建立DatagramSockt实例指定当前端口号,
2)建立数据包接收到字节数组中
3)receive数据包
4)解析数据包,控制台输出
5)关闭

(五)编码题

1.使用基于TCP的Java Socket编程,完成如下功能:
1)要求从客户端录入几个字符,发送到服务器端。
2)由服务器端将接收到的字符进行输出。
3)服务器端向客户端发出“您的信息已收到”作为响应。
4)客户端接收服务器端的响应信息。
提示:
服务器端:PrintWriter out =new PrintWriter(socket.getOutputStream(),true);
客户端:BufferedReader line=new BufferedReader(new InputStreamReader(System.in));

客户端

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
    
    
    public static void main(String[] args)throws Exception {
    
    
        Socket socket=new Socket("192.168.0.37",1811);//根据自己的IP地址更改,端口号自定义。
        Scanner scanner=new Scanner(System.in);
        String s=scanner.next();
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(s);
        bw.newLine();
        bw.flush();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s1=br.readLine();
        System.out.println(s1);
        socket.close();
    }
}

服务器端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    
    
    public static void main(String[] args) throws IOException {
    
    
        ServerSocket serverSocket = new ServerSocket(1811);
        Socket socket=serverSocket.accept();
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s=br.readLine();
        System.out.println(s);

        PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
        pw.append("您的信息已收到");
        pw.flush();
        socket.close();

    }
}

在这里插入图片描述
在这里插入图片描述
2.使用基于UDP的Java Socket编程,完成在线咨询功能:
1)客户向咨询人员咨询。
2)咨询人员给出回答。
3)客户和咨询人员可以一直沟通,直到客户发送bye给咨询人员。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Receive {
    
    
    public static void main(String[] args) throws Exception{
    
    
        DatagramSocket ds=new DatagramSocket(1813);
        while (true) {
    
    
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ds.receive(dp);
            String s = new String(dp.getData(), 0, dp.getLength());

            long l = System.currentTimeMillis();
            Date date = new Date();
            SimpleDateFormat s1 = new SimpleDateFormat("yyyy:mm:dd,hh:mm:ss");
            System.out.println(s1.format(date) + "收到的数据为:" + s);

            if(s.equals("bye")){
    
    
                System.out.println("通信结束");
                break;
            }

            Scanner scanner=new Scanner(System.in);
            System.out.println("请输入要发送的数据:");
            String s2=scanner.next();
            byte[] bytes1=s2.getBytes();
            InetAddress ip=InetAddress.getByName("192.168.0.37");
            int port=1812;
            DatagramPacket dp1=new DatagramPacket(bytes1,bytes1.length,ip,port);
            ds.send(dp1);
            if(s2.equals("bye")){
    
    
                break;
            }
        }
        ds.close();
    }
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Send {
    
    
    public static void main(String[] args) throws Exception{
    
    
        DatagramSocket ds=new DatagramSocket(1812);
        Scanner scanner=new Scanner(System.in);
        while(true){
    
    
            System.out.println("请输入要发送的数据");
            String a=scanner.next();
            byte[] bytes=a.getBytes();
            InetAddress ip=InetAddress.getByName("192.168.0.37");
            int port=1813;
            DatagramPacket dp=new DatagramPacket(bytes,bytes.length,ip,port);
            ds.send(dp);
            if(a.equals("bye")){
    
    
                break;
            }

            byte[] bytes1 = new byte[1024];
            DatagramPacket dp1=new DatagramPacket(bytes1,bytes.length);
            ds.receive(dp1);

            long l=System.currentTimeMillis();
            Date date = new Date();
            SimpleDateFormat s=new SimpleDateFormat("yyyy:mm:dd,hh:mm:ss");

            String b=new String(dp1.getData(),0,dp1.getLength());
            System.out.println(s.format(date)+"收到数据:"+b);
            if(b.equals("bye")){
    
    
                System.out.println("通信结束");
                break;
            }
        }
        ds.close();
    }
}

在这里插入图片描述
在这里插入图片描述
3.使用TCP网络编程完成用户登录功能:
客户端输入用户名和密码,向服务器发出登录请求;服务器接收数据并进行判断,如果用户名和密码均是bjsxt,则登录成功,否则登录失败,返回相应响应信息;客户端接收响应信息并输出登录结果。
1)用户User类已提供构造方法 public User(String username,String password)。
2)客户端采用ObjectOutputStream发送封装了用户名和密码的User对象。
3)服务器端和客户端的类名和方法声明如下所示。

user类

import java.io.Serializable;

public class User implements Serializable {
    
    
    private String name;
    private String pwd;

    public User(){
    
    }

    public User(String name,String pwd){
    
    
        this.name=name;
        this.pwd=pwd;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getPwd() {
    
    
        return pwd;
    }

    public void setPwd(String pwd) {
    
    
        this.pwd = pwd;
    }
}

客户端:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class LoginClient {
    
    
    public static void main(String[] args)throws Exception {
    
    
        Socket socket=new Socket("192.168.0.37",1814);
        Scanner scanner=new Scanner(System.in);
        User user=new User();
        System.out.println("请输入用户名:");
        String name=scanner.next();
        user.setName(name);
        System.out.println("请输入密码");
        String pwd=scanner.next();
        user.setPwd(pwd);

        ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
        oos.writeObject(user);
        oos.flush();

        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s=br.readLine();
        System.out.println(s);
        socket.close();
    }
}

服务端

import java.io.BufferedWriter;
import java.io.ObjectInputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Loginserver {
    
    
    public static void main(String[] args)throws Exception {
    
    
        ServerSocket ss=new ServerSocket(1814);
        Socket socket=ss.accept();
        ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
        Object u=ois.readObject();
        User user=(User)u;
        System.out.println("客户输入得用户名为:"+user.getName());
        System.out.println("客户输入的密码为:"+user.getPwd());

        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        if(user.getName().equals("bjsxt")&&user.getPwd().equals("bjsxt")){
    
    
            bw.write("登录成功");
        }
        else {
    
    
            bw.write("登陆失败");
        }
        bw.newLine();
        bw.flush();

        ss.close();
    }
}

在这里插入图片描述
在这里插入图片描述


java入门基础学习(一)
java入门基础学习(二)
java入门基础学习(三)
java入门基础学习(四)
java入门基础学习(五)
java入门基础学习(六)
java入门基础学习(七)
java入门基础学习(八)
java入门基础学习(九)
java入门基础学习(十)
java进阶之常见对象(一)
java进阶之常见对象(二)
java进阶之冒泡排序
java进阶之选择排序
java进阶之面向对象(封装)
java进阶之面向对象(代码块、继承)
java进阶之面向对象(多态、抽象、接口)
java进阶之匿名内部类、访问修饰符、包

猜你喜欢

转载自blog.csdn.net/qq_45798550/article/details/108302997