网络编程——入门篇(二)

InetAddress类

相关方法:
1.获取本机InetAddress对象 getLocalHost
2.根据指定主机名/域名获取ip地址对象 getByName
3.获取InetAddress对象的主机名 getHostName
4.获取InetAddress对象的地址 getHostAddress

Socket

1.套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。2.通信的两端都要有Socket,是两台机器间通信的端点
3.网络通信其实就是Socket间的通信。
4. Socket允许程序把网络连接当成一个流,数据件典个SOCKeTEIO潮。
5. 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端

一、TCP网络通信编程

1.基于客户端─服务端的网络通信
2.底层使用的是TCP/IP协议
3.应用场景举例:客户端发送数据,服务端接受并显示
4.基于Socket的TCP编程

Server先运行,等待Client
ServerSocket可以由多个socket
在这里插入图片描述

SocketTCP01Server.java

public class SocketTCP01Server {
public static void main(String[] args) throws IOException
{
//思路
//1。在本机的9999端口监听,等待连接
//细节:要求在本机没有其它服务在监听9999
//细节:这个ServerSocket可以通过accept()返回多个Socket[多个客户端连接服务器的并发】
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口监听,等待连接。.");
//2.当没有客户端连接9999端口时,程序会阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务端socket =" + socket.getClass());
//3.通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
InputStream inputStream = socket.getInputStream();
//4。IO读取
byte[] buf=new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) != -1){
system.out.println(new String(buf,0,readLen));//根据读取到的实际长度,显示内容
}
//5.关闭流和socket
inputstream.close();
socket.close();
serverSocket.close();//关闭
}
}

若是Client有回复,代码区别点
在这里插入图片描述

SocketTCPO1Client.java

public class SocketTCPO1Client {
public static void main(String[] args) throws IOException {
//思路
//1。连接服务端〔ip,端口)
//解读:连接本机的 9999端口,如果连接成功,返回Socket对象
Socket socket = new Socket(InetAddress.getLocalHost()9999);//Socket("ip地址")
System.out.println("客户端socket返向=" + socket.getClass());
//2.连接上后,生成Socket,通过socket.getOutputStream()得到和 socket对象关联的输出流对象
OutputStream outputstream = socket.getOutputStream();
//3.通过输出流,写入数据到数据通道
outputstream.write( "hello,server".getBytes());
//4.关闭流对象和socket,必须关闭
outputStream.close();
socket.close(;
System.out.println("客户端退出..... ");
}
}

在这里插入图片描述

  • 案例三:
    1.编写一个服务端,和一个客户端
    2.服务器端在8888端口监听
    3.客户端连接到服务端,发送一张图片e:llqie.png
    4.服务器端接收到客户端发送的图片,保存到src下,发送“收到图片”再退出
    5.客户端接收到服务端发送的“收到图片",再退出
    6.该程序要求使用StreamUtils.java
    TCPFileCopy.java
    在这里插入图片描述

代码:

TCPFileUploadServer.java
public class TCPFileUploadServer {
public static void main(String[] args) throws IOException {
//1.服务端在本机监听8888端口
ServerSocket serverSocket = new ServerSocket(8888);system.out.println("服务端在8888端口监听....");
//2.等待连接
Socket socket = serverSocket.accept();
//3.读取客户端发送的数据
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
byte[] bytes=StreamUtils.streamToByteArray(bis)//4.将得到bytes数组,写入到指定的路径,就得到一个文件了
String destFilePath = "src\\qie2.png" ;
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
bos.write(bytes);
bos.close();

//向客户端回复"收到图片"
//通过socket 获取到输出流(字符)
BufferedWriter writer = new BufferedWriter(new OutputStreamWIriter(socket.getOutputStream()))writer.write("收到图片");
writer.flush();//把内容刷新到数据通道
socket.shutdownOutput(;//设置写入结束标记

//关闭其他资源
writer.close();
bis.close();
socket.close();
serverSocket.close();

}

TCPFileUploadClient.java
public class TCPFileUploadClient {
public static void main(stringL] args) throws Exception {
	//客户端连接服务端8888,得到Socket对象
	Socket socket = new Socket(InetAddress.getLocalHost(),8888);//创建读取磁盘文件的输入流
	String filePath = "e:\\qie.png";
	BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
	//bytes就是filePath对应的字节数组
	byte[] bytes = StreamUtils.streamToByteArray(bis);
	//通过socket获取到输出流,将bytes数据发送给服务端
	Buffered0utputStream bos = new BufferedoutputStream(socket.getOutputStream());
	bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道
	bis.close();
	socket.shutdownOutput();//设置写入数据的结束标记
	
	// 收到从服务器端回复的消息
	InputStream inputstream = socket.getInputstream();
	//使用StreamUtils 的方法,直接将inputStream读取到的内容转成字符串
	String s = streamUtils.streamToString(inputstream);
	System.out.println(s);

	//关闭相关流
	inputStream.close()
	bos.close();
	socket.close();
}

StreamUtils.java
import java.io.BufferedReader;
import java.io.ByteArrayOutputstream;
import java.io.IOException;
import java.io.Inputstream;
import java.io.InputStreamReader;

public class StreamUtils {

/**
 * 功能:将输入流转换成byte[],把文件内容读入到byte[]
 * @param is
 * @return
 * @throws Exception
 */
public static byte[] streamToByteArray(InputStream is) throws Exception{
	ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
	byte[] b = new byte[1024];
	int len;
	while((len=is.read(b))!=-1){
		bos.write(b, 0, len);
	}
	byte[] array = bos.toByteArray();
	bos.close();
	return array;
}
/**
*功能:将InputStream转换成String
*@param
*@return
*@throws Exception
*/
public static string streamToString(InputStream is) throws Exception{
	BufferedReader reader = new BufferedReader(new InputStreamReader(is));
	StringBuilder builder= new StringBuilder();
	String line;
	while((line=reader.readLine())!=null){
		builder.append(line+"\r\n");
	}
	return builder.toString();
}
}

netstat 指令

  1. netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况2.netstat -an | more可以分页显示
    3.要求在dos控制台下执行
    在这里插入图片描述
    当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的

二、UDP网络通信编程[了解]

1.类 DatagramSocket 和 DatagramPacket 实现了基于UDP协议网络程序。
2.UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP
数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
3. DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和
端口号以及接收端的IP地址和端口号。
4. UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方
的连接

附上一个工具类:

Utility.java
/**
 * 工具类的作用:
 * 处理各种情况的用户输入,并且能按照程序员对的需求,得到用户的控制台输入
 */
 
import java.util.Scanner;
import java.util.*;
public class Utility {
    //静态属性
    private static Scanner scanner = new Scanner(System.in);
 
 
    /**
     * 功能:读取键盘输入的一个菜单项,值:1-5范围
     */
    public static char readMenuSelection() {
        char c;
        for (; ; ) {
            String str = readKeyBoard(1, false);
            c = str.charAt(0);//将字符串转换为字符
            if (c != '1' && c != '2' && c != '3' && c != '4' && c != '5') {
                System.out.println("选择错误,请重新输入:");
            } else break;
        }
        return c;
    }
 
    /**
     * 功能:读取键盘输入的一个字符
     */
    public static char readChar() {
        String str = readKeyBoard(1, false);//就是一个字符
        return str.charAt(0);
    }
 
    /**
     * 功能;读取键盘输入的一个字符,如果直接回车,则返回指定的默认值
     * defaultValue 指定的默认值
     * return 默认值或者输入的字符
     */
    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);//要么是空字符,要么??
        return str.length() == 0 ? defaultValue : str.charAt(0);
    }
 
 
    /**
     * 读取键盘输入的整型,长度少于两位
     * return 整数
     */
    public static int readInt() {
        int n;
        for (; ; ) {
            String str = readKeyBoard(2, false);
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.println("选择错误,请重新输入:");
            }
        }
        return n;
    }
 
    /**
     * 功能:读取键盘输入的整数或者默认值,如果直接回车,则返回默认值
     * defaultValue 指定的默认值
     * return 整数或者默认值
     */
    public static int readInt(int defaultValue) {
        int n;
        for (; ; ) {
            String str = readKeyBoard(2, false);
            if (str.equals("")) {
                return defaultValue;
            }
 
            try {
                n = Integer.parseInt(str);
                break;
            } catch (NumberFormatException e) {
                System.out.println("选择错误,请重新输入:");
            }
        }
        return n;
    }
 
    /**
     * 功能:读取键盘输入的指定长度的字符串
     * limit:限制的长度
     * return:指定长度的字符串
     */
    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }
 
    /**
     * 功能:读取键盘输入的指定长度的字符串或者默认值,如果直接回车,返回默认值
     * limit:限制的长度
     * defaultValue 指定的默认值
     * return 指定长度的字符串
     */
    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("") ? defaultValue : str;
    }
 
    /**
     * 功能:读取键盘输入的确认选项,Y或N
     * 将小的功能,封装到一个方法中
     * return Y/N
     */
    public static char readConfirmSelection() {
        System.out.println("请输入你的选择(Y/N)");
        char c;
        for (; ; ) {//无限循环
            //在这里,将接收到字符,转换程大写字母
            //y=>Y,n=>N
            String str = readKeyBoard(1, false).toUpperCase();
            c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                break;
            } else {
                System.out.print("选择错误,请重新输入:");
            }
        }
        return c;
    }
 
    /**
     * 功能:读取键盘输入,如果输入为空,或者输入大于limit的长度,就会提示重新输入
     */
    private static String readKeyBoard(int limit, boolean blankReturn){
        //定义了字符串
        String line="";
 
       //scanner.hasNextLine()判断有没有下一行
        while (scanner.hasNextLine()){
            line=scanner.nextLine();//读取下一行
 
            //如果Line.length=0,即用户没有输入任何内容,直接回车
            if(line.length()==0){
                if(blankReturn) return line;
                else continue;//如果blackRuturn=false,不接受空串,必须输入内容
            }
 
            //如果用户输入的内容大于了limit,就提示重写输入
            //如果用户输入的内容哦个>0<=limit,我就接受
                if(line.length()<1 || line.length()>limit){
                    System.out.println("输入长度(不大于 "+ limit + ")错误,请重新输入:");
                    continue;
                }
                break;
            }
        return line;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值