OSI参考模型
TCP/IP协议栈
TCP/IP协议栈与OSI参考模型的对应关系
TCP/IP协议栈的封装过程
网络编程基本概念
IP地址:标识计算机等网络设备的网络地址,由四个8位的二进制数组成,中间以小数点分隔。 如:166.111.136.3, 166.111.52.80
主机名(hostname):网络地址的助记名,按照域名进行分级管理。如:www.ycu.edu.cn
服务类型(service):网络的各种服务。 如:web服务, ftp服务, smtp服务, Telnet服务等
网络编程:利用操作系统在不同通信协议层次上提供的接口(系统调用、库函数)实现网络进程的安全通信。
网络进程:就是网点机(连入网络的计算机)上运行的程序。网络进程在通信协议中用端口(port)标识,而它驻留的网点机则用其IP地址或域名来标识。
网络编程中有两个主要的问题:
① 如何准确的定位网络上一台或多台主机,
② 找到主机后如何可靠高效的进行数据传输。
网络编程模型:是客户机/服务器(C/S)结构。
端口(Port):指TCP/IP协议中的端口,是逻辑意义上的概念。主机上每一个提供服务的程序都运行在该主机的一 个对外开放的端口上。程序员可以在创建自己的服务程序时使用自定义的端口,通过这个端口号来连接服务进程以接收服务。 如果把IP地址比作一间房子 ,端口就是出入这间房子的门。
① 端口常以16位无符号整数编号(0-65535)。
② 保留端口(0-1023)和动态端口(1024-65535)。
③ 一个端口与使用该端口的服务进程是对应的。
TCP/IP协议(TCP和UDP):
① 四层机构:物理层、网络层、传输层、应用层
② 协议:IP、TCP、UDP、HTTP、FTP、SMTP等
③ TCP:面向连接的服务。可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。比如打电话
④ UDP,无连接的服务。不可靠,差错控制开销较小,传输大小限制在64K以下,不需要建立连接。 比如写信
HTTP及URL
统一资源定位器—URL:URL-- Uniform Resource Locator,表示Internet上某一资源的地址。 浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。
URL的组成
protocol://<host_name>[:port_number][/file_name]
其中:
① 协议名(protocol):指明获取资源所使用的传输协议, 如http、ftp、gopher、file等。
② Host_name:资源名(resourceName)所在的主机。 Port_nubmer:连接时所使用的通信端口号
③ File_name:该资源在主机的完整文件名。
Java网络编程的三种方式
URL编程(获取URL属性信息)
Socket编程(基于TCP 的C/S)
Datagram编程(UDP)
Java网络编程的java.net包
TCP实现网络通信
-URL类
-URLconnection类
-Socket类
-ServerSocket类
UDP实现网络通信
-DatagramPacket类
-DatagramSocket类
-MulticastSocket类
URL编程
1.URL构造方法
- public URL (String URLname); 使用URL对象的字符串URLname来构造URL对象。 例如: URL url=new URL(“http://www. uestc.edu.cn")
- public URL(URL baseurl, String spec); 通过基地址URL和表示相对路径的字符串构造URL对象。 例如:URL uestc=new URL (“http://www. uestc.edu.cn/”); URL indexUestc=new URL(uestc, “index.html”)
- public URL(String protocol, String host, String file); 通过协议名、主机名和文件名构造一个URL对象。 例如:URL u1=new URL(“http”, “www.uestc.edu.cn”, “/index.html”);
- public URL(String protocol,String host, int port, String file); 通过协议名、主机名、端口号和文件名构造一个URL对象。 例如:URL g1=new URL(“http”, “www.uestc.edu.cn”, 8080, “/index.html”);
2.URL的其他方法
获取URL对象属性的方法:
public String getProtocol():获取该URL的协议名
public String getHost() :获取该URL的主机名
public String getPort() :获取该URL的端口号
public String getPath() :获取该URL的文件路径
public String getFile() :获取该URL的文件名
public String getRef() :获取该URL在文件中的相对位置
public String getQuery() :获取该URL的查询名
import java.net.MalformedURLException;
import java.net.URL;
public class URLTest01 {
public static void main(String[] args) {
try{
URL url = new URL("http://www.is.uestc.edu.cn/index.html");
String file = url.getFile();
System.out.println(file);
String host = url.getHost();
System.out.println(host);
int port = url.getPort();
System.out.println(port);
String query = url.getQuery();
System.out.println(query);
String protocol = url.getProtocol();
System.out.println(protocol);
} catch (MalformedURLException e) {
//exception handler code here
}
}
}
注:端口返回-1是为了隐层而免遭攻击。
3.创建和使用URL访问网上资源
1). URLConnection类
URL的方法openStream()只能从网络上读取数据,而不能写。
URLConnection是封装访问远程网络资源一般方法类,通过它可以建立与远程服务器的连接,检查远程资源的一些属性。
URL类中的方法openConnection()可以对URL指向的网络资源进行读写。
public URLConnetion openConnection();
作用:尝试连接URL指向的网络资源,然后返回封装了操作该连接的类java.net.URLConnection的一个实例。
2).URLConnetion类中的常用方法
public InputStream getInputStream();
public OutputStream getOutputStrem();
public URl getURL();
3). URLConnection读/写编程步骤
1)创建一个URL对象u1;
2)使用URL类中的openConnection()方法创建到URL的一个连接对象: URLConnection u1.openConnection()
成功,返回一个URLConnection对象
不成功,抛出IOException异常
3)进行数据的读或写操作;
4)关闭流
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
public class UrlConnection01 {
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.uestc.edu.cn/");
URLConnection conn = url.openConnection(); // 打开连接
InputStream is = conn.getInputStream(); // 得到输入流
OutputStream os = new FileOutputStream("d:\\uestc.txt");
byte[] buffer = new byte[2048];
int length = 0;
while (-1 != (length = is.read(buffer, 0, buffer.length)))
{
os.write(buffer, 0, length);
}
is.close();
os.close();
}
}
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
public class UrlConnection01 {
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.uestc.edu.cn/"); // 用另一种输入流的方法:通过url直接获取
InputStream is = url.openStream();
OutputStream os = new FileOutputStream("d:\\uestc.txt"); byte[]
buffer = new byte[2048];
int length = 0;
while (-1 != (length = is.read(buffer, 0, buffer.length)))
{
os.write(buffer, 0, length);
}
is.close();
os.close();
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class UrlConnection01 {
public static void main(String[] args) throws Exception {
URL url = new URL("https://www.uestc.edu.cn/");
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
while (null != (line = br.readLine()))
{
System.out.println(line);
}
br.close();
}
}
4.InetAddress类代表IP地址
① static InetAddress getByAddress(byte[] addr) 在给定原始 IP 地址的情况下,返回 InetAddress 对象。
② static InetAddress getByAddress(String host, byte[] addr) 根据提供的主机名和 IP 地址创建 InetAddress。
③ static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。
④ String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。
⑤ String getHostName()
⑥ static InetAddress getLocalHost() 返回本地主机。
⑦ String toString() 将此 IP 地址转换为 String。
import java.io.IOException;
import java.net.InetAddress;
public class GetInetAddress {
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getLocalHost();
System.out.println(address);
address = InetAddress.getByName("www.uestc.edu.cn");
System.out.println(address);
}
}
Socket编程
1.Socket连接过程
2.Socket通信实现步骤
1、创建ServerSocket和Socket
2、打开连接Socket的输入/输出流
3、按照协议(通常是TCP/UDP)对Socket进行读写操作
4、关闭输入/输出流,关闭Socket
3.Socket通信模型
4.服务器端ServerSocket类的构造方法
1、public ServerSocket(int port) throws IOException
创建绑定到特定端口的服务器套接字。
2、public ServerSocket(int port, int backlog) throws IOException
利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
3、public ServerSocket(int port, int backlog, InetAddress address) throws IOException
使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
4、public ServerSocket() throws IOException
创建非绑定服务器套接字。
5.服务器端ServerSocket类的方法
1、public int getLocalPort()
返回此套接字在其上侦听的端口。
2、public Socket accept() throws IOException
侦听并接受到此套接字的连接。
3、public void setSoTimeout(int timeout)
通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位。
4、public void bind(SocketAddress host, int backlog)
将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
6.客户端Socket类的构造方法
1、public Socket(String host, int port) throws UnknownHostException, IOException.
创建一个流套接字并将其连接到指定主机上的指定端口号。
2、public Socket(InetAddress host, int port) throws IOException
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
3、public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.
创建一个套接字并将其连接到指定远程主机上的指定远程端口。
4、public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.
创建一个套接字并将其连接到指定远程地址上的指定远程端口。
5、public Socket()
通过系统默认类型的 SocketImpl 创建未连接套接字
7.客户端Socket类的方法
1、public void connect(SocketAddress host, int timeout) throws IOException 将此套接字连接到服务器,并指定一个超时值。
2、public InetAddress getInetAddress() 返回套接字连接的地址。
3、public int getPort() 返回此套接字连接到的远程端口。
4、public int getLocalPort() 返回此套接字绑定到的本地端口。
5、public SocketAddress getRemoteSocketAddress() 返回此套接字连接的端点的地址,如果未连接则返回 null。
6、public InputStream getInputStream() throws IOException 返回此套接字的输入流。
7、public OutputStream getOutputStream() throws IOException 返回此套接字的输出流。
8、public void close() throws IOException 关闭此套接字。
eg:
1.Server服务器端
a、创建ServerSocket对象,同时绑定监听端口
b、通过accept()方法监听客户端的请求
c、建立连接后,通过输入流读取客户端发送的请求信息
d、通过输出流向客户端发送响应信息
e、关闭相应资源
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(100000);
}
public void run() {
while(true) {
try {
System.out.println(" 等待远程连接,端口号为: " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println(" 远程主机地址: " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
}catch(IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = Integer.parseInt(args[0]); // int port = 6606;
try {
Thread t = new GreetingServer(port);
t.run();
}catch(IOException e) {
e.printStackTrace();
}
}
}
2.client客户端
a、创建Socket对象,指明需要连接的服务器的地址和端口号
b、建立连接后,通过输出流向服务器端发送请求信息
c、通过输入流获取服务器的响应信息
d、关闭相应资源
import java.net.*;
import java.io.*;
public class GreetingClient {
public static void main(String [] args) {
String serverName = args[0]; //String serverName = "localhost";
int port = Integer.parseInt(args[1]); //int port = 6606;
try {
System.out.println(" 连接到主机: " + serverName + " ,端口号: " + port);
Socket client = new Socket(serverName, port); System.out.println(" 远程主机地址: " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer); System.out.println(" 服务器响应: " + in.readUTF());
client.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
eg2:简易聊天室
1)服务器端
package chatroom;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
private int duankou = 9000;// 端口号
private ServerSocket server;// 声明服务器
private static Socket socket;// 声明客户端
private String serName;
public Server() {
try {
init();
} catch (IOException e) {
e.printStackTrace();
}
}
private void init() throws IOException {
server = new ServerSocket(duankou);
System.out.println("------服务器已开启--------");
System.out.println("请输入服务器名字:");
Scanner sc = new Scanner(System.in);
serName = sc.next();
while (true) {
socket = server.accept();
hands(socket);
sc.close();
}
}
private void hands(Socket socket) {
String key = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
System.out.println("监听到的客户端:" + key);
Thread thread = new Thread(new ThreadSocket(socket));
thread.setName(serName);
thread.start();
}
public static void main(String[] args) {
Server server = new Server();
}
}
2)Socket
package chatroom;
import java.io.IOException;
import java.net.Socket;
public class ThreadSocket implements Runnable {
private Socket socket;
public ThreadSocket(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
Thread threadReader = new Thread(new ThreadReader(socket.getInputStream()));
Thread threadWriter = new Thread(new ThreadWriter(socket.getOutputStream()));
threadReader.start();
threadWriter.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3)线程读消息
package chatroom;
import java.io.IOException;
import java.io.InputStream;
public class ThreadReader implements Runnable {
private InputStream is;
public ThreadReader(InputStream is) {
this.is = is;
}
@Override
public void run() {
try {
while (true) {
byte[] b = new byte[1024];
int length = is.read(b);
String message = new String(b, 0, length);
System.out.println(Thread.currentThread().getName() + ":" + message);
}
} catch (IOException e) { e.printStackTrace();}
}
}
4)线程写消息
package chatroom;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
public class ThreadWriter implements Runnable {
private OutputStream os;
public ThreadWriter(OutputStream os) {
this.os = os;
}
@Override
public void run() {
try {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println(Thread.currentThread().getName() + " 说: ");
String message = sc.next();
os.write(message.getBytes());
os.flush();
}
} catch (IOException e) {e.printStackTrace();}
}
}
5)客户端
package chatroom;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private int port = 9000;
private String ip = "127.0.0.1";
private static Socket socket;
private String cliName;
public Client() {
try {
init();
} catch (Exception e) {e.printStackTrace();}
}
private void init() throws Exception {
System.out.println("-----客户端已开启-----");
System.out.println("请输入客户端名字:");
Scanner sc = new Scanner(System.in);
cliName = sc.next();
socket = new Socket(ip, port);
}
public void hands() throws Exception {
Thread threadReader = new Thread(new ThreadReader(socket.getInputStream()), Thread.currentThread().getName());
Thread threadWriter = new Thread(new ThreadWriter(socket.getOutputStream()));
threadWriter.setName(cliName);
threadReader.start();
threadWriter.start();
}
public static void main(String[] args) throws Exception {
Client client = new Client();
client.hands();
}
}