목차
IP 및 포트 운영
- 클래스: InetAddress - IP 캡슐화
- 클래스: InetSocketAddress - IP, 포트 캡슐화
참고: IP와 포트를 직접 조작할 수 없으며 개체 작업으로 캡슐화해야 합니다.
InetAddress는 생성자 권한 수정자가 기본값이기 때문에 객체를 직접 생성할 수 없지만 클래스 이름을 통해 직접 호출할 수 있는 정적 메서드가 있습니다.
InetAddress address = InetAddress.getByName("localhost");
System.out.println(address);//域名/IP地址
//getByName()中可以封装ip、域名等可以与ip映射的东西
System.out.println(address.getHostName());//获取域名
System.out.println(address.getHostAddress());//获取ip地址
//关于类InetSocketAddress
InetSocketAddress inetSocketAddress = new InetSocketAddress("192.168.199.217", 8080);
System.out.println(inetSocketAddress.getHostName());//获得域名
System.out.println(inetSocketAddress.getPort());//获得端口号
InetAddress address1 = inetSocketAddress.getAddress();//获得ip地址对象
System.out.println(address1.getHostName());//获得域名
System.out.println(address1.getHostAddress());//获得IP地址
커뮤니케이션 관련
- TCP/IP 아키텍처: 네트워크 통신의 기반.
- 통신을 위한 두 가지 중요한 조건: IP+port(포트)
- 통신 프로토콜: 장치 간에 데이터를 전송할 때는 일정한 규칙을 따라야 하는데 이 규칙을 통신 프로토콜이라고 합니다.
소켓
역할: 애플리케이션 계층은 전송 계층 프로토콜(TCP/UDP)을 얻습니다.
TCP 프로토콜
이름: 전송 제어 프로토콜
특징:
- 신뢰할 수 있는 연결 지향적
- 연결을 설정하기 위해 3번의 핸드셰이크가 설정되고 연결을 해제하기 위해 4번의 핸드셰이크가 해제됩니다.
알아채다:
- 클라이언트 요청을 기다리기 위해 먼저 서버를 열어야 함
- 클라이언트와 서버 간의 양방향 통신, 클라이언트가 연결을 닫고 싶습니다 입력하면 연결을 닫습니다.
TCP 연습 동작
고객
public class Customer {
public static void main(String[] args) throws IOException {
//创建套接字,指定服务器的IP和端口
Socket socket = new Socket("127.0.0.1", 6666);
socket.setSoTimeout(1000000);//设置连接超时时间,以ms为单位
OutputStream outputStream = socket.getOutputStream();//获取输出流用来发送数据
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//变成可处理字符串的输出流——装饰模式
InputStream inputStream = socket.getInputStream();//获取输入流用来读数据
DataInputStream dataInputStream = new DataInputStream(inputStream);//变成可处理字符串的输入流——装饰模式
String s1="";
while(!s1.equals("关闭")) {
String s = new Scanner(System.in).nextLine();
dataOutputStream.writeUTF(s);//给服务器发送数据——不阻塞
s1 = dataInputStream.readUTF();//读取服务端信息——其为阻塞方法
System.out.println(s1);
}
//以下为关流
dataOutputStream.close();
outputStream.close();
socket.close();
}
}
섬기는 사람
public class Service {
public static void main(String[] args) throws IOException {
//创建套接字,监听6666端口
ServerSocket serverSocket = new ServerSocket(6666);
//accept()为阻塞方法,等待用户端数据,什么时候收到数据什么时候执行,返回值为客户端socket,接到这个socket后,客户端和服务器才真正建立连接,才真正可以通信了
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();//获取输入流,用来得到客户端数据
DataInputStream dataInputStream = new DataInputStream(inputStream);//利用字符串处理流来读取字符串
OutputStream outputStream = accept.getOutputStream();//获取输出流,用来向客户端写数据
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
String s1="";
while(!s1.equals("关闭")) {
String s = dataInputStream.readUTF();//读取客户端数据——其为阻塞方法
System.out.println(s);//信息
if(s.equals("我想关闭连接")){
s1="关闭";
dataOutputStream.writeUTF(s1);
}else {
s1 = new Scanner(System.in).nextLine();
dataOutputStream.writeUTF(s1);//不阻塞
}
}
//以下为关流
dataInputStream.close();
inputStream.close();
accept.close();//客户端socket
serverSocket.close();
}
}//全写好之后运行该服务等待客户端请求
UDP 프로토콜
이름: 사용자 데이터그램 프로토콜
특징:
- 비연결 지향
- 데이터 패킷을 분할하여 하나씩 대상으로 보내고 마지막으로 서버 측에서 요약합니다(패킷 손실 문제가 있음).
알아채다:
- 보내는 사람과 받는 사람이 같다
- 발신자와 수신자 간의 양방향 통신, 발신자가 다음 채팅에 들어가면 중지
UDP 연습 작업
보내는 사람
public class Send {
public static void main(String[] args) throws IOException {
//准备套接字,指定发送方的端口号
DatagramSocket datagramSocket = new DatagramSocket(8888);
String s1="";
while(!s1.equals("bye bye")) {
//发送阶段
//准备数据包
String s = new Scanner(System.in).nextLine();
byte[] bytes = s.getBytes();
//里面传接收方的IP地址对象及端口
DatagramPacket localhost = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 6666);
//向目标地址发送数据包
datagramSocket.send(localhost);//不是阻塞方法
//接收阶段
byte[] b = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(b, b.length);
datagramSocket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
s1 = new String(data, 0, datagramPacket.getLength());
System.out.println(s1);
}
//关流
datagramSocket.close();
}
}
수화기
public class Get {
public static void main(String[] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket(6666);//指定接收方的端口号
boolean flag=true;
while(flag) {
//接收阶段
//搞一个空数据包用来接收对方传过来的数据
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
//接收对方发过来的数据包放入datagramPacket数据包中进行填充
datagramSocket.receive(datagramPacket);//其为阻塞方法,接收数据包后,datagramPacket里面的内容就填充好了
//取出数据
byte[] data = datagramPacket.getData();
String s = new String(data, 0, datagramPacket.getLength());//取出特定长度的字节数据转化为字符串类型
System.out.println(s);
if(s.equals("下次再聊")){
DatagramPacket end = new DatagramPacket("bye bye".getBytes(), "bye bye".getBytes().length, InetAddress.getByName("localhost"), 8888);
datagramSocket.send(end);
flag=false;
}else {
//发送阶段
//准备数据包
String s1 = new Scanner(System.in).nextLine();
byte[] b = s1.getBytes();
DatagramPacket localhost = new DatagramPacket(b, b.length, InetAddress.getByName("localhost"), 8888);
//向目标地址发送数据包
datagramSocket.send(localhost);//不是阻塞方法
}
}
//关流
datagramSocket.close();
}
}
자바 HTTP 요청
요청을 수신하기 위해 tomcat 서비스를 엽니다.
@RestController
@RequestMapping("/hello")
public class MyController {
@GetMapping("/getName")
public String responseName(String name){
return "你的名字为"+name;
}
@PostMapping("/getUser")
public String responseUser(@RequestBody Map<String,Object> map){
System.out.println(map);
return "你的post请求发送成功";
}
}
참고: 여기서 사용한 포트는 8088입니다.
HTTP는 GET 요청을 보냅니다.
public class HttpTest {
public static void main(String[] args) throws Exception{
//定义一个url字符串
String urlstr = "http://localhost:8088/hello/getName?name=lili";
//将url字符串转换为url对象
URL url = new URL(urlstr);
//通过该url对象创建连接
URLConnection urlConnection = url.openConnection();
//URLConnection为一个抽象类,我们需要HttpURLConnection
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
//使用url.openConnection()创建了连接,connect()方法可有可无;
//如果使用HttpURLConnection conn=new HttpURLConnection(new URL(“路径”)),则需要使用connect()方法进行连接。
//httpURLConnection.connect();
//设置请求头
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
//设置请求类型
httpURLConnection.setRequestMethod("GET");
//设置连接超时时间10s
httpURLConnection.setConnectTimeout(10000);
//设置读取超时时间10秒
httpURLConnection.setReadTimeout(10000);
//允许从远程服务器中读取数据,默认为true
httpURLConnection.setDoInput(true);
//获取HttpURLConnection的输入流,用来读数据
InputStream inputStream = httpURLConnection.getInputStream();
//装饰模式,处理流对该流进行处理
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
//该处理流用来增加处理效率
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
StringBuilder all = new StringBuilder();
//若该行数据不为空,则追加到all
while ((line = bufferedReader.readLine()) != null) {
all.append(line);
}
System.out.println(all);
//获得响应状态码
int responseCode = httpURLConnection.getResponseCode();
System.out.println(responseCode);
//关流
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
//关闭连接
httpURLConnection.disconnect();
}
}
HTTP 전송 POST 요청
public class HttpTestPost {
public static void main(String[] args) throws Exception{
//定义一个url字符串
String urlstr = "http://localhost:8088/hello/getUser";
//将url字符串转换为url对象
URL url = new URL(urlstr);
//通过该url对象创建连接
URLConnection urlConnection = url.openConnection();
//URLConnection为一个抽象类,我们需要HttpURLConnection
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
//设置请求头
httpURLConnection.setRequestProperty("appId", "app_service");
//设置请求类型
httpURLConnection.setRequestMethod("POST");
//设置请求体格式,这里设置的是json格式
httpURLConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8;");
//设置连接超时时间10s
httpURLConnection.setConnectTimeout(10000);
//设置请求体
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("name","lili");
map.put("age",18);
//将usermap转化为json格式
ObjectMapper mapper = new ObjectMapper();
String jsonBody = mapper.writeValueAsString(map);
//设置成true,向远程服务器写数据,默认是false
httpURLConnection.setDoOutput(true);
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(jsonBody.getBytes());
outputStream.flush();
//关流
outputStream.close();
//允许从远程服务器中读取数据,默认为true
//httpURLConnection.setDoInput(true);
//获取HttpURLConnection的输入流,用来读数据
InputStream inputStream = httpURLConnection.getInputStream();
//装饰模式,处理流对该流进行处理
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
//该处理流用来增加处理效率
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
StringBuilder all = new StringBuilder();
//若该行数据不为空,则追加到all
while ((line = bufferedReader.readLine()) != null) {
all.append(line);
}
System.out.println(all);
//获得响应状态码
int responseCode = httpURLConnection.getResponseCode();
System.out.println(responseCode);
//关流
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
//关闭连接
httpURLConnection.disconnect();
}
}
알아채다:
- 연결을 생성하기 위해 url.openConnection()을 사용한 후에는 연결을 생성할 필요가 없습니다.
- HttpURLConnection conn=new HttpURLConnection(new URL("path"))를 사용하면 connect() 메서드를 사용하여 연결해야 합니다.
- httpURLConnection.setDoInput(true) 메소드는 원격 서버에서 데이터 읽기를 허용하는 것입니다. 기본값은 true입니다.
- httpURLConnection.setDoOutput(true) 메소드는 원격 서버에 데이터 쓰기를 허용하는 것입니다. 기본값은 false입니다.