网络编程的常识
当发送数据时,按照上述七层协议从前向后一层层进行加包处理再发送;
当接收数据时,按照上述七层协议从后向前一层层进行拆包处理再显示;
-
IP地址
如:192.168.1.1 - 是绝大多数路由器的默认登录地址,设置账号和密码及Mac地址过滤
IP地址 - 是互联网中的唯一地址标识,根据IP地址可以定位到具体某一台设备。
IP地址本质上是由32位二进制组成的整数,叫做IPv4,当然也有128位二进制组成的整数,叫做IPv6,目前的主流还是IPv4。
日常生活中采用点分十进制表示法进行IP地址的描述,也就是将每个字节的二进制整数转换为一个十进制整数,不同的十进制整数之间采用小数点隔开。
如: 0x01020304 => 1.2.3.4
IP地址其实就是一个虚拟的整数,本身和计算机没有关系.实际上IP地址是绑定了网址的物理地址(Mac),网卡的物理地址是出厂就设定,无重复.IP地址其实找到的是网卡.
-
端口号
端口号 - 是设备中具体进程的标识,也就是根据端口号可以定位到具体某个进程。
网络编程提供:IP地址 + 端口号。
端口号本质上是由16位二进制组成的整体,表示范围是:0-65535,其中0-1024之间的端口号通常被系统占用,因此编程从1025开始使用。
特殊端口: HTTP:80 FTP:21 Oracle:1521 Mysql:3306 Tomcat:8080
基于tcp协议的编程模型(重点)
-
C/S架构的简介
在C/S模式下客户向服务器发出服务请求,服务器接收到请求后提供相应服务。
客户端:为每个用户所专有的,负责执行前台功能。
服务器:由多个用户共享的信息与功能,招待后台服务。
-
ServerSocket类
主要用于描述服务器套接字信息。
ServerSocket(int port) - 根据参数指定的端口号来构造对象.
Socket accept() - 侦听并接收到此套接字的连接请求.
void close() - 用于关闭套接字.
-
Socket类
Socket(String host,int port) - 根据指定主机名和端口来构造对象.
InputStream getInputStream() - 用于获取当前套接字的输入流.
OutputStream getOutputStream() - 用于获取当前套接字的输出流.
void close() - 用于关闭套接字.
-
编程模型
服务器:
(1)创建ServerSocket类型的对象并提供端口号;
(2)等待客户端的连接请求,调用accept方法;
(3)使用输入输出流通信;
(4)关闭Socket;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.net.ServerSocket; import java.net.Socket; public class ServerStringTest { public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(8888); while(true) { System.out.println("等待客户端的连接请求..."); Socket s = ss.accept(); System.out.println("客户端" + s.getInetAddress() +"连接成功!"); new ServerThread(s).start(); } } catch(Exception e) { e.printStackTrace(); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.InetAddress; import java.net.Socket; public class ServerThread extends Thread { private Socket s; public ServerThread(Socket s) { this.s = s; } @Override public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintStream ps = new PrintStream(s.getOutputStream()); while (true) { String msg = br.readLine(); InetAddress ia = s.getInetAddress(); System.out.println("客户端" + ia + "发来的数据内容是:" + msg); if ("bye".equalsIgnoreCase(msg)) { System.out.println("客户端" + ia + "已下线!"); break; } ps.println("I received!"); } ps.close(); br.close(); s.close(); } catch(Exception e) { e.printStackTrace(); } } }
|
客户端:
(1)创建Socket类型的对象并提供服务器的IP地址和端口号;
(2)使用输入输出流通信;
(3)关闭Socket;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class ClientStringTest { public static void main(String[] args) { try { Socket s = new Socket("XDL-20170621QCO", 8888); System.out.println("连接服务器成功!");
Scanner sc = new Scanner(System.in); PrintStream ps = new PrintStream(s.getOutputStream()); BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream()));
while(true) { System.out.println("请输入要发送的内容:"); String str = sc.nextLine(); ps.println(str); System.out.println("客户端发送数据成功!"); if("bye".equalsIgnoreCase(str)) { System.out.println("聊天结束!"); break; } String msg = br.readLine(); }
br.close(); ps.close(); sc.close(); s.close(); } catch(Exception e) { e.printStackTrace(); } } }
|
-
注意事项
客户端Socket与服务器Socket对应,都包括输入,输出流.
客户端的socket.getInputStream()连接于服务器socket.getOutputStream().
客户端的socket.getOutputStream()连接于服务器socket.getInputStream().