2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Socket API:t ovat järjestelmän tarjoamia. Eri järjestelmien tarjoamat API:t ovat erilaisia, mutta nämä järjestelmärajapinnat on edelleen kapseloitu Javaan.
UDP:n socket-sovellusliittymä keskittyy kahteen luokkaan: DatagramSocket ja DatagramPacket
Tämän luokan toimintoa voidaan pitää kaukosäätimenä "verkkokortin käyttämiseen", eli verkkokortin luku- ja kirjoitustoimintoihin, jotka voidaan ymmärtää tiedostojen lukemiseksi ja kirjoittamiseksi.
Tarjolla on useita menetelmiä:
Tämä luokka kuvaa UDP-datagrammit DatagramPacket-objekti vastaa UDP-datagrammia Kerran lähetetty ja vastaanotettu DatagramPacket-objekti.
Kaiku: Asiakas lähettää palvelimelle erilaisia pyyntöjä ja palvelin palauttaa erilaisia vastauksia. Mutta kaiku tässä on se, mitä asiakas pyytää palvelimelta, ja palvelin vastaa ilman laskelmia tai liiketoimintalogiikkaa.
public class udpEchoServer {
public DatagramSocket socket = null;
public udpEchoServer(int port) throws SocketException {
socket = new DatagramSocket(port);
}
public void start() throws IOException {
System.out.println("服务器启动!!!");
while (true) {
//接受客户端请求
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
socket.receive(requestPacket);
//为了更好处理数据并方便打印,将接受的数据转化为字符串操作
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
//处理客户端的请求(算术计算或者业务逻辑)
String response = this.process(request);
//将处理完的请求返还给客户端
DatagramPacket resposePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,
requestPacket.getSocketAddress());
socket.send(resposePacket);
//打印客户端的ip地址端口号和接收客户端的数据以及处理完客户端后的数据
System.out.printf("[%s:%d] req = %s,resp = %sn",requestPacket.getAddress(),requestPacket.getPort(),
request,response);
}
}
public String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
udpEchoServer udpEchoServer = new udpEchoServer(9999);
udpEchoServer.start();
}
}
DatagramPacket-objekti edustaa datagrammia. UDP-datagrammi koostuu otsikosta ja hyötykuormasta. Otsikon IP-osoite ja porttinumero ovat DatagramPacket-luokan attribuutteja, mutta hyötykuormaluokkaa ei ole annettu, joten ohjelmoijan on tehtävä se. Edellyttäen, että kuten munkki pyytää almua, sinun on tarjottava kulho almulle, ja sitten jokainen perhe laittaa ruokaa kulhoon. Koska datagrammin olemus on binääridata, tarjoan hyötykuormana .
Asiakkaalta saadut tiedot on palautettava asiakkaalle palvelimen käsittelyn jälkeen, joten palvelimen käsittelemien tietojen tallentamiseksi on luotava DatagramPacket-objekti, jonka jälkeen palvelin lähettää sen asiakkaalle. Tällä hetkellä DatagramPacket-objektin ei tarvitse jättää käsitellyt tiedot tähän objektiin. Koska asiakkaan IP-osoite ja porttinumero tallennetaan tietoja vastaanotettaessa, vain asiakkaan IP-osoite ja portin numero tallennetaan, kun lähetät sen asiakkaalle. Sinun on hankittava asiakkaan IP-osoite ja porttinumero requestPacket.getSocketAddress() -palvelun kautta.
Koska palvelin on kiinteä, voit asettaa portin numeron suoraan itse. Portin numero luodaan, kun palvelin käynnistyy.
Miksi tarvitsen porttinumeron IP-osoitteen?
Jotta osapuolten välinen viestintä onnistuisi, näiden neljän keskeisen indikaattorin on oltava läsnä:
Lähdeportti, lähde-IP, kohdeportti, kohde-IP
Näiden neljän ydinindikaattorin avulla voidaan saavuttaa verkkoyhteys kahden osapuolen välillä. Tässä ei ole palvelimen IP-osoitetta, koska asiakas ja palvelin ovat samassa isännässä. Voimme käyttää IP-osoitetta edustamaan 172.0.0.1, joka tunnetaan myös nimellä loopback IP.
public class udpEchoClient {
private DatagramSocket socket = null;
private String serverIp;
private int serverProt;
public udpEchoClient(String serverIp, int serverProt) throws SocketException {
socket = new DatagramSocket();
this.serverIp = serverIp;
this.serverProt = serverProt;
}
public void start() throws IOException {
System.out.println("客户端启动!");
//1.从控制台获取字符串
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("请输入要发送的请求: ");
String request = scanner.nextLine();
//2.将输入的字符串发送给服务器,还要将发送的目标确定,IP和端口号
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length,
InetAddress.getByName(serverIp), serverProt);
socket.send(requestPacket);
//3.从服务器读取到经过处理的响应
DatagramPacket responsePackt = new DatagramPacket(new byte[4096], 4096);
socket.receive(responsePackt);
//将响应打印在控制台
String response = new String(responsePackt.getData(), 0, responsePackt.getLength());
System.out.println(response);
}
}
public static void main(String[] args) throws IOException {
udpEchoClient udpEchoClient = new udpEchoClient("127.0.0.1",9999);
udpEchoClient.start();
}
}
Konsolista vastaanotetulle merkkijonolle requestPacket-objekti hankkii merkkijonoobjektin viitteen ja pituuden sekä oman IP-osoitteensa ja Prot-osoitteensa ja lähettää sen sitten palvelimelle socketin lähetysmenetelmän kautta.
Jotta saat vastauksen palvelimelta, sinun on luotava responsePackt-objekti ja luotava tyhjä tavutaulukko etukäteen vastaanottaaksesi palvelimelta saadun vastauksen.
Erota joitain menetelmiä:
Ennen menetelmien erottamista meidän on ymmärrettävä tavujen, merkkien ja koodausmuotojen käsitteet
Tavut ja merkit ovat pohjimmiltaan binaarisia, mikä on dataa, kuten 0101, koska tietokone tunnistaa vain 0101:n.
Tavu: Tavu on tietokoneen tietojen tallennuksen perusyksikkö. 1 tavu on 8 bittiä. Jokainen bitti voi olla 0 tai 1, mikä tarkoittaa, että yksi tavu voi edustaa 256 eri arvoa.
Merkki: Merkki on tekstiinformaation esittämisen perusyksikkö. Eri koodausmuotojen mukaan merkkiä vastaavien tavujen määrä on erilainen Siirrä tiedot ja tallenna tiedot.
Koodausmuoto:
Menetelmät ovat erilaisia:
Tässä voimme soveltaa periytymisen ja polymorfismin ideoita tämän palvelimen toteuttamiseen, koska olennainen ero tämän sanakirjan käännöspalvelimen ja kaikupalvelimen välillä on vastausten käsittely, joten voimme periä ja käyttää uudelleen toistuvaa koodia ja laajentaa vaadittua koodia.
public class udpDictServer extends udpEchoServer{
HashMap<String,String> map = null;
public udpDictServer(int port) throws SocketException {
super(port);
map = new HashMap<>();
map.put("server","服务");
map.put("client","客户端");
map.put("cat","🐱");
map.put("dog","🐕");
map.put("pig","🐖");
}
@Override
public String process(String request) {
return map.getOrDefault(request, "该词汇没有查询到");
}
public static void main(String[] args) throws IOException {
udpDictServer udpDictServer = new udpDictServer(9999);
udpDictServer.start();
}
}
Tämän sanakirjan käännöksen toteuttamiseksi tarvitset myös kartan tietorakenteessa ja käytät kartan avainarvo-pareja tietojen tallentamiseen.
Silloin tiettyjen liiketoimintojen tarvitsee vain kirjoittaa prosessimenetelmä uudelleen.
Tässä suoritettaessa, vaikka tämä viittaa pääluokan udpEchoServer-olioon, koska udpDictServer-aliluokka perii udpEchoServer-emoluokan ja ohittaa prosessimenetelmän, polymorfisen ominaisuuden vuoksi suoritettu prosessimenetelmä on itse asiassa alaluokan prosessi.