标签:
通过使用套接字来达到进程间通信目的的编程就是网络编程
网络编程最重要的两点
1、定位目标主机(ip地址和端口)
2、如何传输数据(协议)
面向连接相对可靠传输协议编程
TCP:传输控制协议
案列模型:打电话通话
要点:基于TCP网络编程的核心在于建立连接,通过连接里获得流对象来实现数据的传输的目的。
备注:TCP编程的核心在于连接,以及从连接获得的流对象。
面向无连接不是很可靠的传输协议
UDP:用户数据报协议
案列模型:发送短信、日常寄送包裹
要点:基于UDP网络编程的核心在于构建数据包对象,从DatagramSocket对象中发送和接收数据包对象。
备注:UDP编程的核心在于数据报中
InetAddress类
InetAddress对象表示IP地址,由于java是面向对象编程的语言,所以为了给IP匹配就以InetAddress来表示IP地址。直接使用字符串表示IP地址也没关系。
URL类
URL对象表示同意资源定位符,同InetAddress类似,url同样也可以使用字符串表示,只不过java是面向对象语言因此使用了URL类。
URLConnection类
URLConnection是一个抽象类,表示一个连接,其主要实现由HttpURLConnection类,http连接。
发送请求时就会使用到这个类。
Socket套接字
A socket is an endpoint for communication between two machines.
ServerSocket服务器套接字
This class implements server sockets. A server socket waits for requests to come in over the network.
It performs some operation
备注:可以把Socket和ServerSocket简单理解为连接端点。
DatagramSocket数据报套接字
This class represents a socket for sending and receiving datagram packets.
A datagram socket is the sending or receiving point for a packet delivery service.
Each packet sent or received on a datagram socket is individually addressed and routed.
Multiple packets sent from one machine to another may be routed differently,
and may arrive in any order.
备注:理解为邮局
DatagramPacket数据报
This class represents a datagram packet.
备注:理解为数据包裹
Client端代码
/**
* 控制台输入信息,聊天小程序。
*
* @author xuyi3
* @2016年7月18日 @上午9:35:08
* @Client2
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class Client {
public static void main(String[] args) throws Exception {
// 客户端新建Socket对象,必须制定主机地址和端口
Socket socket = new Socket("192.168.1.187", 9999);
// 通过Socket对象获得连接的输入流
InputStream in = socket.getInputStream();
// 通过Socket对象获得连接的输出流
OutputStream out = socket.getOutputStream();
// 使用更方便的缓冲包装流来操作
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
// 控制台输入流
Scanner scanner = new Scanner(System.in);
while (true) {
// 输出信息给服务器
System.out.print("客户端:");
String line = null;
line = scanner.nextLine();
writer.write(line);
// 以下两步非常重要,不写会让对方的输入流一直阻塞。
writer.newLine();
writer.flush();
// 读取服务器信息
String string = reader.readLine();
System.out.println("服务器:" + string);
}
}
}
Server端代码
/**
* 控制台输入信息,聊天小程序
*
* @author xuyi3
* @2016年7月18日 @上午10:24:56
* @Server2
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class Server2 {
public static void main(String[] args) throws Exception {
// 新建服务端ServerSocket对象,必须要指定监听端口
ServerSocket serverSocket = new ServerSocket(9999);
// 阻塞监听...
System.out.println("阻塞监听");
// 监听端口创建一个新的连接
Socket socket = serverSocket.accept();
// 通过Socket对象获得连接的输入流
InputStream in = socket.getInputStream();
// 通过Socket对象获得连接的输出流
OutputStream out = socket.getOutputStream();
// 使用更方便的缓冲包装流来操作
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
// 控制台输入流
Scanner scanner = new Scanner(System.in);
while (true) {
// 读取客户端信息
String string = reader.readLine();
System.out.println("客户端:" + string);
// 输出信息给服务器
System.out.print("服务器:");
String line = null;
line = scanner.nextLine();
writer.write(line);
// 以下两步非常重要否则会出问题,是对方输入流一直阻塞。
writer.newLine();
writer.flush();
}
}
}
Client客户端代码
/**
* 基于UDP的聊天程序
*
* @author xuyi3
* @2016年7月18日 @上午10:52:55
* @UdpClient
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class UdpClient {
public static void main(String[] args) throws Exception {
// 数据包Socket对象,该对象既可以发送数据包也可以接收数据包(类似邮局既可以寄件又可以收件)
DatagramSocket datagramSocket = new DatagramSocket(8888);
Scanner scanner = new Scanner(System.in);
while (true) {
// 发送数据
String line = scanner.nextLine();
// 数据包包裹对象,该对象用来承载数据信息(类似寄件过程中的包裹,发送数据包里面通常会包含要发送目标地址信息、数据大小等)
DatagramPacket sendPacket = new DatagramPacket(line.getBytes(), 0, line.length(),
InetAddress.getLocalHost(), 8889);
datagramSocket.send(sendPacket);
// 接收数据
byte[] tem = new byte[1024];
//接收数据包通常只需要指定数据大小即可
DatagramPacket receivePacket = new DatagramPacket(tem, tem.length);
datagramSocket.receive(receivePacket);
byte[] data = receivePacket.getData();
System.out.println("服务器:" + new String(data, 0, data.length));
}
}
}
Server端代码
/**
* 基于UDP的聊天程序
*
* @author xuyi3
* @2016年7月18日 @上午11:08:49
* @UdpServer
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class UdpServer {
public static void main(String[] args) throws Exception {
// 数据包Socket对象,该对象既可以发送数据包也可以接收数据包(类似邮局既可以寄件又可以收件)
DatagramSocket datagramSocket = new DatagramSocket(8889);
Scanner scanner = new Scanner(System.in);
while (true) {
// 接收数据
byte[] tem = new byte[1024];
// 接收数据包通常只需要指定数据大小即可
DatagramPacket receivePacket = new DatagramPacket(tem, tem.length);
datagramSocket.receive(receivePacket);
byte[] data = receivePacket.getData();
System.out.println("客户端:" + new String(data, 0, data.length));
// 发送数据
String line = scanner.nextLine();
// 数据包包裹对象,该对象用来承载数据信息(类似寄件过程中的包裹,里面通常会包含要发送目标地址信息、数据大小等)
DatagramPacket sendPacket = new DatagramPacket(line.getBytes(), 0, line.length(),
InetAddress.getLocalHost(), 8888);
datagramSocket.send(sendPacket);
}
}
}
Client客户端代码
/**
* 基于TCP实现文件上传和下载功能
*
* @author xuyi3
* @2016年7月18日 @上午11:28:51
* @UploadClient
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class UploadClient {
public static void main(String[] args) throws Exception {
// 客户端新建Socket对象,必须制定主机地址和端口
Socket socket = new Socket("192.168.1.187", 9999);
// 通过Socket对象获得连接的输出流
OutputStream out = socket.getOutputStream();
// 要上传的文件路径
FileInputStream fileInputStream = new FileInputStream(new File("e:/git.png"));
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
fileInputStream.close();
out.flush();
out.close();
}
}
Server端代码
/**
*
* 基于TCP实现文件上传和下载功能
*
* @author xuyi3
* @2016年7月18日 @下午1:27:02
* @UploadServer
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class UploadServer {
public static void main(String[] args) throws Exception {
// 新建服务端ServerSocket对象,必须要指定监听端口
ServerSocket serverSocket = new ServerSocket(9999);
// 阻塞监听...
System.out.println("阻塞监听");
// 监听端口创建一个新的连接
Socket socket = serverSocket.accept();
// 通过Socket对象获得连接的输入流
InputStream in = socket.getInputStream();
// 指定要下载的文件保存路径
FileOutputStream fileOutputStream = new FileOutputStream(new File("e:/gitcopy.png"));
byte[] bytes = new byte[1024];
int len = 0;
while ((len = in.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, len);
}
fileOutputStream.close();
System.out.println("传输完成");
}
}
多客户端聊天程序,客户端代码不变,服务器端代码需要调整。思路:每连接过来一个客户端就新建一个线程单独给予处理这个客户端,
因此要抽取公共代码到线程类里面。
ServerThread线程类代码
public class ServerThread implements Runnable {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 通过Socket对象获得连接的输入流
InputStream in = socket.getInputStream();
// 通过Socket对象获得连接的输出流
OutputStream out = socket.getOutputStream();
// 使用更方便的缓冲包装流来操作
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
// 控制台输入流
Scanner scanner = new Scanner(System.in);
while (true) {
// 读取客户端信息
String string = reader.readLine();
System.out.println("客户端:" + string);
// 输出信息给服务器
System.out.print("服务器:");
String line = null;
line = scanner.nextLine();
writer.write(line);
// 以下两步非常重要否则会出问题,是对方输入流一直阻塞。
writer.newLine();
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Server端代码
/**
* 控制台输入信息,聊天小程序<br>
* 多客户端聊天,使用多线程为每个客户端新建一个独立线程来使用<br>
*
* 客户端代码不用修改,只需要修改服务器端代码即可<br>
*
*
* @author xuyi3
* @2016年7月18日 @上午10:24:56
* @Server2
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class Server3 {
public static void main(String[] args) throws Exception {
// 新建服务端ServerSocket对象,必须要指定监听端口
ServerSocket serverSocket = new ServerSocket(9999);
while (true) {
// 阻塞监听...
System.out.println("阻塞监听");
// 监听端口创建一个新的连接
Socket socket = serverSocket.accept();
new Thread(new ServerThread(socket)).start();
}
}
}
网络编程的实际用途可能有很多,但是其核心的两种编程模型就是TCP编程模型和UDP编程模型,总体思路都是相同的。
1、http://www.ibm.com/developerworks/cn/education/linux/l-sock/l-sock.html
2、http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html
3、https://en.wikipedia.org/wiki/Network_socket
标签:
原文地址:http://blog.csdn.net/nicewuranran/article/details/51946874