如何实现网络通信?
通信双方地址:
- 地址ip
- 端口号
- 127.0.0.1:8080
OSI七层模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2Vt3rrJ-1641116549495)(C:UsersyanyuAppDataRoamingTyporatypora-user-imagesimage-20211225142933939.png)]
小结:
- 网络编程中有两个主要问题
- 如何准确定位到网络上的一台或者多台主机
- 找到主机之后如何通信
- 网络编程中的要素
- IP和端口号 IP
- 网咯通信协议 UDP、TCP
- IP和端口号 IP
- 万物皆对象
ip地址:InetAdddress
- 唯一定义网络上的一台或者多台地址
- ping 127.0.0.1:本机 localhost
- ip地址的分类
- IPV4IPV6
- IPV4,127.0.0.1,四个字节,32位,0-255,42亿
- IPV6,128位
- 公网–私网
- ABCD类地址
- 192.168.xx.xx
- IPV4IPV6
- 域名:记忆IP问题
- IP:纯数字
- URL:统一资源定界符,DNS服务器
//获取ip,InetAddress类 public static void main(String[] args) { InetAddress ip=null; try { ip = InetAddress.getByName("127.0.0.1"); System.out.println(ip); ip = InetAddress.getByName("www.baidu.com"); System.out.println(ip); System.out.println(InetAddress.getLocalHost()); } catch (UnknownHostException e) { e.printStackTrace(); } }1.4 端口
端口计算机上的表示一个进程
-
不同进程具有不同端口,用来区分软件
-
一个int大小,0-65535
-
TCP,UDP, 单个协议下,同一端口并不冲突
-
公共端口 0 - 1024
-
http:80
-
https:443
-
ftp:21
-
Telent:23
-
-
程序注册端口:1024-49151,用户程序公用
-
Tomcat:8080
-
MySql:3306
-
Oracle:1521
-
-
动态、私有:49152-65535
netstat -ano #查看所有端口 netstat -ano| findstr “5900” #查看指定端口 takelist | findstr "8696" #查看相应端口
-
socketAddress类,将地址和端口结合
InetAddress ip=null; try { ip = InetAddress.getByName("127.0.0.1"); InetSocketAddress socketAddress = new InetSocketAddress(ip, 80); InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 80); System.out.println(socketAddress); System.out.println(socketAddress1); socketAddress.getAddress(); socketAddress.getPort(); } catch (UnknownHostException e) { e.printStackTrace(); }1.5 通信协议
procedure、protocol
通信协议:通信规则,波特率,信道,…
TCP协议:传输控制协议,Transmission Control Protocol
UDP协议:用户数据报协议,User Data Protocol
TCP:可靠全双工通信,建立连接后通信
三次握手
A:你好 B:你好 A:我们开始聊天!
四次挥手
A:我要断开连接了 B:你真的断开连接了吗 B:你确定你断开连接 A:是的
UDP:不可靠半双工通信,不建立连接,直接向ip:端口发送消息
1.6 TCP实现聊天java socket在创建构造函数的时候是创建的连接对象的地址,如果不使用有参构造,那么需要手动connect(),一般网络连接流程如下:
![img](https://img-blog.csdnimg.cn/img_convert/41eb6e3df828bedae464a1f430ce4aba.png)
package com.zp; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class TcpService { static OutputStream os =null; static InputStream is=null; static Socket socket = null; static ServerSocket serverSocket = null; public static void main(String[] args) { Scanner cin = new Scanner (System.in); try { System.out.println("服务器启动"); //构造ServerSocket实例,指定端口监听客户端的连接请求 serverSocket = new ServerSocket(8080); // 建立跟客户端的连接 socket = serverSocket.accept(); // 向客户端发送消息 is = socket.getInputStream(); os = socket.getOutputStream(); InputStreamReader isr=new InputStreamReader(is,"utf-8"); OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8"); //osw.write(msg); // 接受客户端的响应 new Thread() { public void run() { // TODO Auto-generated method stub while (true) { //byte b[] = new byte[1024]; char[] cha=new char[1024]; int len=0; try { len = isr.read(cha); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("小明说:"+new String(cha,0,len)); } } }.start(); //向客户端发送消息 new Thread(){ public void run(){ // TODO Auto-generated method stub while(cin.hasNext()){ String str=cin.next(); try { //osw.write(str); os.write(str.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } catch (IOException e) { e.printStackTrace(); } finally { } } }
package com.zp; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Scanner; public class TcpClient { static Socket socket = null; static InputStream is = null; static OutputStream os = null; public static void main(String[] args) { Scanner cin = new Scanner (System.in); try { // 对服务端发起连接请求 System.out.println("已经连接服务器"); socket = new Socket("localhost", 8080); is = socket.getInputStream(); os = socket.getOutputStream(); InputStreamReader isr=new InputStreamReader(is,"utf-8"); OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8"); os.write("已经接服务器。".getBytes()); //接收服务器信息 new Thread() { public void run() { // TODO Auto-generated method stub while (true) { //byte b[] = new byte[1024]; char[] cha=new char[1024]; int len=0; try { len = isr.read(cha); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("小红说:"+new String(cha,0,len)); } } }.start(); // 给服务端发送响应信息 new Thread(){ public void run(){ // TODO Auto-generated method stub while(cin.hasNext()){ String str=cin.next(); try { //osw.write(str); os.write(str.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注意:
- socket IO流读不到会自动阻塞,除非遇到了EOF或者IOException
- 正是因此,我觉得,TCP实现全双工通信就分成两个线程
UDP一般工作流程:
package com.zp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; public class UDPSender implements Runnable{ DatagramSocket socket = null; BufferedReader reader = null; private int fromPort; private String toIP; private int toPort; public UDPSender(int fromPort, String toIP, int toPort) { this.fromPort = fromPort; this.toIP = toIP; this.toPort = toPort; try { socket = new DatagramSocket(fromPort); reader = new BufferedReader(new InputStreamReader(System.in)); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { while (true){ try { String data = reader.readLine(); byte[] datas = data.getBytes(); System.out.println(datas.length); DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort)); socket.send(packet); if (data.equals("bye")){ break; } } catch (IOException exception) { exception.printStackTrace(); } } socket.close(); } }
package com.zp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPReceiver implements Runnable{ DatagramSocket socket = null; private int port; private String msgFrom; public UDPReceiver(int port, String msgFrom) { this.port = port; this.msgFrom = msgFrom; try { socket = new DatagramSocket(port); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true){ try { //准备接受包裹 byte[] container = new byte[1024]; DatagramPacket packet = new DatagramPacket(container, 0, container.length); socket.receive(packet); //断开连接 bye byte[] data = packet.getData(); String receiveData = new String(data, 0, data.length); System.out.println(msgFrom + ":" + receiveData); if (receiveData.equals("bye")){ break; } } catch (IOException exception) { exception.printStackTrace(); } } socket.close(); } }
注意:
- UDP是只管发送的IP,接受他是没有IP的,因为他是不事先建立连接的通信
1.8 URL
https://www.baidu.com/
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS 域名解析 www.baidu.com/ xxx.xxx.xxx
- 协议://ip地址:端口/项目名/资源
public class URLDemo01 { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123"); System.out.println(url.getProtocol()); //协议 System.out.println(url.getHost()); //主机ip System.out.println(url.getPort()); //端口 System.out.println(url.getPath()); //文件地址 System.out.println(url.getFile()); //文件全路径 System.out.println(url.getQuery()); //参数 } }
- 网络资源下载
public class UrlDown { public static void main(String[] args) throws Exception { //1.下载地址 URL url = new URL(""); //2.连接到这个资源 HTTP HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream inputStream = urlConnection.getInputStream(); FileOutputStream fos = new FileOutputStream("tu.jpg"); byte[] buffer = new byte[1024]; int len; while((len=inputStream.read(buffer)) != -1){ fos.write(buffer, 0, len);//写出这个数据 } fos.close(); inputStream.close(); urlConnection.connect(); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)