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 指令
- 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;
}
}