一 TCP/IP 之Socket
1.1 Socket简介
socket中文名叫套接字,应用程序通过套接字向网络发送请求或者应答请求,最早是unix上的一套网络通信标准,已被广泛移植到其他平台,在internet上一般运行着多个服务软件,同时提供了几种服务,每种服务都打开一个socket并绑定到端口上,不同的端口对应与不同的服务进程。socket实质上提供了进程通信的端点,网络上的两个程序通过一个双向的通讯链路实现数据的交换,这个双向链路的一端称为一个socket。
1.2 socket分类
1.2.1原始式套接字
该接口允许对较低层次协议,如IP直接访问,可以接收本机网卡上的数据包与数据帧,对监听网络流量和分析很有用。
1.2.2流式套接字
提供了一个面向连接,可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收,对应使用的是TCP协议。
1.2.3数据报式套接字
无连接服务。数据包以独立包形势被发送,不提供无差错保证,数据可能丢失或重复,并且接收顺序无序,其实它对应使用的是udp协议
1.3 如何使用socket
1.3.1 Socket API
1.3.2 ServerSocket API
1.3.3 服务端创建步骤
1 建立一个服务器socket,绑定指定端口并开始监听
2 使用accept()方法阻塞等待监听
3 建立输入与输出流
4 在已有的协议上产生绘画
5 使用close关闭流的socket
1.3.4 客户端创建步骤
1 建立客户端socket连接,指定服务器的位置及端口号
2 得到socket读写流
3 利用流按照一定的协议对socket进行读写操作
4 使用close()关闭socket操作
1.3.5通信流程
如上图所示服务端创建一个套接子服务,创建一个阻塞式的服务等待连接,客户端向服务端发动连接请求,建立连接,客户端向服务端发送请求,服务端接收到请求以后给客户端返回数据,客户端关闭套接字,通信结束。
1.3.6 1v1字符串通信事例程序
服务端
public class ServerSocketS {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(8888);
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
//字节流转换为字符流
BufferedReader buf=
new BufferedReader(new InputStreamReader(inputStream));
String flow=null;
while((flow=buf.readLine())!=null){
System.out.println(flow);
}
}
}
客户端
public class ClientSocket {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket=new Socket("127.0.0.1", 8888);
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(outputStream);
printWriter.write("你好");
printWriter.flush();
printWriter.close();
}
}
1.3.7 1v1对象通信事例程序
通过socket做对象传输就是通过对象序列化的方式进行传输的
服务器端
public class ServerSocketObject {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket=new ServerSocket(8787);
Socket accept = serverSocket.accept();
//阻塞等待客户端输入
InputStream inputStream = accept.getInputStream();
OutputStream outputStream = accept.getOutputStream();
ObjectInputStream in=new ObjectInputStream(inputStream);
User u=(User) in.readObject();
System.out.println(u.getName());
System.out.println(u.getAge());
PrintWriter writer=new PrintWriter(outputStream);
writer.write("成功登陆");
writer.flush();
writer.close();
inputStream.close();
outputStream.close();
serverSocket.close();
}
}
客户端
public class ClientSocketObject {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1", 8787);
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
User user=new User();
user.setName("张三");
user.setAge(18);
ObjectOutputStream out=new ObjectOutputStream(outputStream);
out.writeObject(user);
BufferedReader reader
=new BufferedReader(new InputStreamReader(inputStream));
String str=null;
while((str=reader.readLine())!=null){
System.out.println(str);
}
inputStream.close();
reader.close();
out.close();
socket.close();
}
}
对象类
public class User implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.3.8 1vN对象通信实例
在实际的工作中,往往是客户端发起一个连接与客户端建立了链接之后,服务端启动一个连接线程,然后又等待下一次通信的接入。
服务端
public class ServerSocketObject {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//服务器端一直开着 每获取到一个连接的情况下开启一个服务线程
ServerSocket serverSocket=new ServerSocket(8787);
Socket socket =null;
int num=0;
while(true){
socket=serverSocket.accept();
SocketThread socketThread=new SocketThread(socket);
socketThread.start();
num++;
System.out.println("第"+num+"个连接客户");
}
}
}
public class SocketThread extends Thread{
Socket socket=null;
public SocketThread(Socket socket){
this.socket=socket;
}
public void run(){
try{
//阻塞等待客户端输入
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
ObjectInputStream in=new ObjectInputStream(inputStream);
User u=(User) in.readObject();
System.out.println(u.getName());
System.out.println(u.getAge());
PrintWriter writer=new PrintWriter(outputStream);
writer.write("成功登陆");
writer.flush();
writer.close();
inputStream.close();
outputStream.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
客户端
public class ClientSocketObject {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1", 8787);
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
User user=new User();
user.setName("李四");
user.setAge(18);
ObjectOutputStream out=new ObjectOutputStream(outputStream);
out.writeObject(user);
BufferedReader reader
=new BufferedReader(new InputStreamReader(inputStream));
String str=null;
while((str=reader.readLine())!=null){
System.out.println(str);
}
inputStream.close();
reader.close();
out.close();
socket.close();
}
}
实体类
public class User implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
二 UDP之 Socket
2.1 Socket简介
不需要建立连接,不需要完全可靠的数据传输,简单不可靠,及时,快速
客户端要向外发送数据,必须用datagramPacket封装数据报,进行发送。
2.2 DatagramSocket API
2.3 通信实例
2.3.1 服务端
public class UapServer {
public static void main(String[] args) throws Exception {
DatagramSocket socket=new DatagramSocket(8888);
//接收客户端请求
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
socket.receive(dp);
String text=new String(buf,0,dp.getLength());
System.out.println("客户端数据:"+text);
//服务端给客户端返回数据
String tex="你好我是服务器";
byte[] br=tex.getBytes();
SocketAddress socketAddress = dp.getSocketAddress();
DatagramPacket send=new DatagramPacket(br,br.length,socketAddress);
socket.send(send);
socket.close();
}
}
2.3.2 客户端
public class UapClient {
public static void main(String[] args) throws Exception {
String st="你好我是客户端";
byte[] by=st.getBytes();
InetAddress addre = InetAddress.getByName("localhost");
DatagramSocket socket=new DatagramSocket();
DatagramPacket datagramPacket=
new DatagramPacket(by, by.length,addre,8888);
socket.send(datagramPacket);
byte[] bs=new byte[1024];
DatagramPacket packet=new DatagramPacket(bs, bs.length);
socket.receive(packet);
String s=new String(bs,0,packet.getLength());
System.out.println(s);
socket.close();
}
}
三 URL&URLConnection
3.1概述
java 提供了两个类,在这两个类里封装了大部分 Web 相关的各种操作。这两个类是 URL 类和 URLConnection 类。
3.2 URL 类
java.net.URL 类定义了一个统一的资源定位器,它是指向互联网“资源”的指针。可以定
位互联网上的资源。并且在定位的资源存在的情况下,允许以流的方式读取该资源。这些资源可能是一个简单的文件,也可能是一个目录,甚至可以是一个复杂的对象,比如搜索引擎。
在 JDK 6.0 中 URL 类提供 6 种构造方法,在这里我们介绍常用的两种,第一种是
URL(String spec),它只有一个构造参数,这个构造方法表示用指定的字符串创建一个 URL 对
象,这个字符串呢它是一个 URL 地址,比如 http://localhost:8080/index.html,我们就可以
根据这个 URL 地址字符串的表示形式创建一个 URL 对象。第二种构造方法有四个构造参数,protocol 表示网络协议,host 表示主机名,port 表示端口号,file 表示资源路径。这个构造方法会使用指定的网络协议,主机名,端口号和资源路径创建一个 URL 对象。
try {
URL url = new URL("http://localhost:8080/index.jsp");
System.out.println("此 URL 的主机是: " + url.getHost());
System.out.println("此 URL 的协议是: " + url.getProtocol());
System.out.println("此 URL 的端口是: " + url.getPort());
System.out.println("此 URL 的路径是: " + url.getPath());
} catch (Exception e) {
e.printStackTrace();
}
3.3 URLConnection 类
URLConnection 类代表应用程序和 URL 之间的通信连接。此类的实例可以通过调用 URL 对
象的openConnection()方法获得,URLConnection对象可用于读取或写入 URL对象引用的资源。我们要向创建一个程序和 URL 之间的连接,也就是说我们要创建一个 URLConnection 对象,那么我们首先要创建一个 URL 对象 ,然后在 URL 对象上调用 openConnection()方法来创建一个连接对象,也就是说 URL 对象的 openConnection()方法会返回一个 URLConnection 对象。因此呢,URLConnection 对象就只有一个构造方法,构造参数就是一个 URL 对象,接下来,下面我们要了解的是 URLConnection 类的常用方法。
URL url = new URL("http://www.jb-aptech.com.cn");
URLConnection con = url.openConnection();
System.out.println("使用的 URL 是:" + con.getURL());
System.out.println("内容类型:" + con.getContentType());
System.out.println("内容长度:" + con.getContentLength());
System.out.println("最后修改:" + con.getLastModified());
System.out.println("超时设置:" + con.getConnectTimeout());