网络通信
数据的发送和接收,通过端口进行
端口号的范围0-65535,自己使用的时候别使用0-1024(被系统占用)
InetAddress
把IP地址面向对象
得到本机的IP地址对应的InetAdress对象getLocalHost,得到任意IP地址的InetAdress对象getByName
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Demo1 {
public static void main(String[] args) throws UnknownHostException {
//本机的InerAddress对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost.getAddress());
System.out.println(localHost.getHostName());
//获取任意一台主机的IP地址的InetAddress对象
InetAddress host1 = InetAddress.getByName("172.28.67.76");
System.out.println(host1.getHostName());
}
}
udp协议
面向无连接的、直接收发数据,不管对方在不在,速度快,不安全
创建Socket对象,使用DatagramSocket
发送数据
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
public class UdpSend {
public static void main(String[] args) throws IOException {
//使用udp协议实现数据的发送
//1.创建socket节点
DatagramSocket datagramSocket = new DatagramSocket();
//2.准备要发送的数据
String data="hello,world";
byte[] arr = data.getBytes(StandardCharsets.UTF_8);
//3.发送数据 void send(DatagramPacket p)发送的数据需要打包,
// 参数1表示要发送的数据(字节数组),参数2表示要发送数据的长度,
// 参数3表示接收数据的IP地址,参数4表示用来接受数据的端口号
DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length, InetAddress.getByName("172.28.67.76"),12345);
//4.发送数据
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}
接收数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpReceive {
public static void main(String[] args) throws IOException {
//接收方的对象需要监听端口
DatagramSocket receive = new DatagramSocket(12345);
//接收数据 void receive(DatagramPacket)
byte[] arr = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(arr,arr.length);//创建用来接收数据的数据包
receive.receive(datagramPacket);
byte[] data = datagramPacket.getData();
String ip = datagramPacket.getAddress().getHostAddress();
System.out.println(ip+":"+new String(data,0,datagramPacket.getLength()));
receive.close();
}
}
tcp协议
面向连接的,速度慢,安全
确认和是否和对方连接上:三次握手,发出请求,对方给响应,发送发再次发送响应表示收到了接收方的响应
Server服务端,被连接
Client客户端,主动进行连接的一方
tcp协议中的节点对象使Socket(InetAddress address,int port)创建,Socket内部有字节输入流和字节输出流,使用输入输出流实现数据的传输通信
服务端可能有多个客户端与其建立连接,为了确定服务端的消息传输不出错,服务端应该拿到客户端的Socket对象,相当于客户端和服务端使用一个流对象,使用accept方法得到客户端对象
client
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class tcpClient {
public static void main(String[] args) throws IOException {
//获取socket对象 Socket(InetAddress adress,int 12347)参数1表示服务器地址,参数2表示服务器的监听端口
Socket socket = new Socket(InetAddress.getByName("172.28.67.76"),12347);
//获取其中的字符输出流对象
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello".getBytes(StandardCharsets.UTF_8));
InputStream inputStream = socket.getInputStream();
byte[] arr = new byte[1024];
int read = inputStream.read(arr);
System.out.println(new String(arr,0,read));
}
}
Server
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class tcpServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12347);
Socket so = serverSocket.accept();
byte[] arr = new byte[1024];
InputStream inputStream = so.getInputStream();
int len = inputStream.read(arr);
System.out.println(new String(arr,0,len));
OutputStream outputStream = so.getOutputStream();
outputStream.write("你好".getBytes(StandardCharsets.UTF_8));
}
}
文本文件的上传
客户端:读取一个本地文件,每次读取的数据发送给服务端,读取服务端发送过来的“上传成功”
public class UploadClient {
public static void main(String[] args) throws IOException {
/*实现文本文件的上传:把文件从客户端上传到服务端,上传完成时,服务端返回"上传成功",客户端显示 “上传成功”
客户端:读取一个本地文件
每次读取的数据发送给服务端
读取服务端发送过来的 "上传成功"
*/
System.out.println("客户端启动了");
Socket socket=new Socket(InetAddress.getByName("172.28.67.17"),18888);
//创建读取文本文件的字符缓冲输入流对象
BufferedReader bufferedReader=new BufferedReader(new FileReader("files\\temp.txt"));
//创建给服务端发送数据的字符输出流对象
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(outputStream,true);
//创建读取服务端数据的字符输入流对象
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader1=new BufferedReader(new InputStreamReader(inputStream));
//循环读取本地文件,发送给服务端
String line =null;
while((line=bufferedReader.readLine())!=null)
{
printWriter.println(line);
}
//客户端给服务端发送一个结束标记
socket.shutdownOutput();
bufferedReader.close();
//读取服务端返回的“上传成功”
String str = bufferedReader1.readLine();
System.out.println(str);
socket.close();
}
}
服务端
public class UploadServer {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动了");
ServerSocket serverSocket=new ServerSocket(18888);
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress());
/*
读取客户端发送的数据
把数据写入到服务端某个文件中
给客户端发送“上传成功”
*/
//创建读取客户端数据的字符输入流对象
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
//创建把数据写入到服务端某个文件中的字符输出流对象
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("files\\temp_copy.txt"));
//创建给客户端发送“上传成功” 的字符输出流对象
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(outputStream,true);
//循环读取客户端发送的数据
String line = null;
while((line=bufferedReader.readLine())!=null)//服务端读客户端,读不到null
{
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedWriter.close();
//给客户端发送“上传成功”
printWriter.println("上传成功");
socket.close();
serverSocket.close();
}
}
文件的上传
客户端
public class UploadClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getByName("172.28.67.17"),19999);
//创建读取文件的字节输入流对象
FileInputStream fileInputStream = new FileInputStream("images\\33.jpg");
//向服务端发送的字节输出流
OutputStream outputStream = socket.getOutputStream();
//读取服务器返回的“上传成功”
InputStream inputStream = socket.getInputStream();
//循环读取文件,把读取的数据发送给服务端
byte[] arr = new byte[1024];
int len;
while ((len=fileInputStream.read(arr))!=-1){
outputStream.write(arr,0,len);
}
socket.shutdownOutput();
fileInputStream.close();
//读取服务器返回的数据
len = inputStream.read(arr);
System.out.println(new String(arr,0,len));
socket.close();
}
}
服务端
public class UploadServer {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动了");
ServerSocket serverSocket = new ServerSocket(19999);
Socket accept = serverSocket.accept();
System.out.println("得到来自客户端"+accept.getInetAddress().getHostName()+"连接");
//创建读取客户端数据的字节输入流
InputStream inputStream = accept.getInputStream();
//创建写入到本地文件的文件输出流对象
FileOutputStream fileOutputStream = new FileOutputStream("images\\33_copy.jpg");
//创建向客户端发送数据的输出流
OutputStream outputStream = accept.getOutputStream();
//循环读取客户端的数据
byte[] arr = new byte[1024];
int len;
while((len=inputStream.read(arr))!=-1){
fileOutputStream.write(arr,0,len);
}
fileOutputStream.close();
outputStream.write("上传成功".getBytes());
accept.close();
outputStream.close();
}
}
作业
实现将客户端从键盘输入的小写字母转为大写字母并返回的服务端功能
客户端
//实现小写字母的转换
public class ChangeClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getByName("172.28.67.17"),19999);
//创建读取键盘输入的小写字符串的缓冲输入流对象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
//创建给服务端发送数据的字符输出流
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream,true);
//创建接收服务端发送过来的数据
InputStream inputStream = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line=bufferedReader.readLine())!=null){
if("over".equals(line))
break;
printWriter.println(line);
System.out.println(br.readLine());
}
bufferedReader.close();
socket.close();
}
}
服务端
public class ChangeServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(19999);
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostName()+"连接到服务端了");
//接收k端数据的对象
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//给客户端发数据的字符输出流
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream,true);
//循环读取客户端发送来的数据
String line;
while ((line=bufferedReader.readLine())!=null){
printWriter.println(line.toUpperCase());
}
socket.close();
}
}