文章目录
1 网络编程基本概念
2 网络编程TCP协议
1、 TCP 程序概述
Tcp 是一个可靠的协议,面向连接的协议
实现TCP程序,需要编写服务器端和客户端,Java API 为我们提供le Java.net 包,为实现网络应用程序提供类。
ServerSocket: 此类实现服务器套接字
Socket: 此类实现客户端套接字
Socket 是网络驱动层提供给应用程序编程的接口和一种机制。
实现服务器端与客户端程序
客户端:
public class Socket extends Object 套接字是两台机器间通信的端点
Socket(String host, int port): 创建一个流套接字并将其连接到指定主机上的指定端口号
InputStream getInputSream() 返回此套接字的输入流
OutputStream getOutputStream() 返回此套接字的输出流
void setSoTimeout(int timeout) 启用/禁用带有指定超时值的SO_TIMEOUT, 以毫秒为单位
Echo: 意思为应答,程序的功能是客户端向服务器发送一个字符串,服务器不做任何处理,直接把字符串返回给客户端,Echo 程序是最为基本的客户/ 服务器程序
3 TCP实现ECHO程序
public class EchoClientDemo {
public static void main(String[] args){
// 创建一个Socket 对象,指定要连接的服务器
try {
Socket socket = new Socket("localhost",6666);
// 获取socket 的输入输出流
PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
ps.println("hello");
ps.flush();
String info = br.readLine();
System.out.println(info);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class EchoServerDemo {
public static void main(String[] args){
try {
ServerSocket server = new ServerSocket(6666);
System.out.println("服务器已经启动,等待客户端连接");
Socket socket = server.accept();
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String info = br.readLine(); // 通过输入流读取网络数据, 如果没有数据,那么会阻塞
System.out.println(info);
// 获取输出流,向客户端返回消息
PrintStream ps = new PrintStream(new
BufferedOutputStream(socket.getOutputStream()));
ps.println("echo"+ info);
ps.flush();
ps.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 服务器与多客户端通信
目前为止我们编写的程序中,服务器只能同时处理一个客户端连接,要想服务器同时支持多个客户端的连接,就必须加入多线程的处理机制,将每一个连接的客户端都创建一个新的线程对象
// 用来处理客户端请求的线程任务
public class MultiServerDemo {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
try {
ServerSocket server = new ServerSocket(6666);
System.out.println("服务器已经启动,正在等待连接");
while (true) {
Socket s = server.accept();
System.out.println(s.getInetAddress().getHostAddress());
es.execute(new UserThread(s));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 用来处理客户端请求的线程任务
class UserThread implements Runnable {
private Socket s;
public UserThread(Socket s) {
this.s = s;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));
String info = br.readLine();
System.out.println(info);
ps.println("echo " + info);
ps.flush();
ps.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5 多客户端之间的通信
服务器可以与多个客户端实现通信了,那我们真正的目的是要实现多个客户端之间的通信,使用TCP协议实现的方案是: 客户端将数据包通过服务器中转,发送到另一个客户端。
public class MultiServerDemo {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
try {
ServerSocket server = new ServerSocket(6666);
System.out.println("服务器已经启动,正在等待连接");
while (true) {
Socket s = server.accept();
System.out.println(s.getInetAddress().getHostAddress());
es.execute(new UserThread(s));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 用来处理客户端请求的线程任务
class UserThread implements Runnable {
private Socket s;
public UserThread(Socket s) {
this.s = s;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintStream ps = new PrintStream(new BufferedOutputStream(s.getOutputStream()));
String info = br.readLine();
System.out.println(info);
ps.println("echo " + info);
ps.flush();
ps.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiClientDemo {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
// 创建一个Socket 对象,指定要连接的服务器
try {
Socket socket = new Socket("localhost",6666);
// 获取socket 的输入输出流
PrintStream ps = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("请输入:");
String info = input.nextLine();
ps.println(info);
ps.flush();
info = br.readLine();
System.out.println(info);
} catch (IOException e) {
e.printStackTrace();
}
}
}
6 网络编程UDP协议
UDP 是User Datagram protocol 简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,他在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性不能保证,每个被传输的数据报必须限定在64KB之内。
DatagramPacket: 此类表示数据报包
DatagramSocket: 表示用来发送和连接数据报包的套接字
public class UDPServerDemo {
public static void main(String[] args) {
String info = "good good 学习, 天天 up up";
byte[] bytes = info.getBytes();
DatagramPacket dp;
try {
dp = new DatagramPacket(
bytes,
0,
bytes.length,
InetAddress.getByName("127.0.0.1"),
8888);
DatagramSocket socket = new DatagramSocket(9000);
socket.send(dp);
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class UDPClientDemo {
public static void main(String[] args) {
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
try {
DatagramSocket socket = new DatagramSocket(8000);
System.out.println("正在接受数据");
socket.receive(dp);
String s = new String(dp.getData(), 0, dp.getLength());
System.out.println(s);
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
7 URL
代表一个统一资源定位符,它是指向互联网“资源”的指针。抽象类URLConnection是所有类的超类,他代表应用程序和URL之间的通信链接
public class URLDemo {
public static void main(String[] args){
try{
URL url = new URL(" ");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("c:\\yield.jpg"));
byte[] bytes = new byte[1024];
int len = -1;
while((len = in.read(bytes))!= -1){
out.write(bytes,0,len);
out.flush();
}
in.close();
out.close();
System.out.println("下载成功");
}catch (Exception e){
}
}
}
8 MINA 框架
开发一个Mina 应用,简单的说,就是创建连接,设定过滤规则,缩写自己的消息处理器
入门案例
public class Server {
public static void main(String[] args) {
// 创建一个非阻塞的Server 端Socket NIO
SocketAcceptor acceptor = new NioSocketAcceptor();
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
// 设定一个过滤器, 一行一行的读取数据
// chain.addLast("name", new ProtocolCodecFilter(new TextLineCodecFactory()));
// 设定过滤器以对象为单位读取数据
chain.addLast("objectFilter",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
// 设置服务器端的消息处理器
acceptor.setHandler(new MinaServerHandler());
int port = 9999; // 服务器的端口号
acceptor.setHandler(new MinaServerHandler());
try {
// 绑定端口,启动服务器(不会阻塞,立即返回)
acceptor.bind(new InetSocketAddress(port));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Mina Server 已启动");
}
}
public class MinaServerHandler extends IoHandlerAdapter {
@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
System.out.println("welcome client "+session.getRemoteAddress());
}
@Override
public void sessionClosed(IoSession session) throws Exception {
super.sessionClosed(session);
System.out.println("客户端关闭");
}
// 接受消息
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
super.messageReceived(session, message);
// String msg = (String) message;
Message msg = (Message)message;
System.out.println("收到客户端发来的消息 "+msg);
msg.setInfo("吃好吃的");
// 向客户端发送消息对象
session.write("echo:"+msg);
}
}
public class Client {
public static void main(String[] args) {
// 创建连接
NioSocketConnector connector = new NioSocketConnector();
DefaultIoFilterChainBuilder chain = connector.getFilterChain();
// chain.addLast("myChin", new ProtocolCodecFilter(new TextLineCodecFactory()));
chain.addLast("objectFilter", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
connector.setHandler(new MinaClientHandler());
connector.setConnectTimeoutMillis(10000);
// 连接服务器
ConnectFuture cf = connector.connect(new InetSocketAddress("localhost", 9999));
cf.awaitUninterruptibly();
Scanner input = new Scanner(System.in);
while (true) {
// System.out.println("请输入");
// String info = input.nextLine();
// cf.getSession().write(info);
// 以对象的方式传输数据
Message msg = new Message();
System.out.println("from:");
msg.setFrom(input.nextLine());
System.out.println("to");
msg.setInfo(input.nextLine());
System.out.println("info");
msg.setInfo(input.nextLine());
msg.setType("send");
cf.getSession().write(msg);
}
}
}
public class MinaClientHandler extends IoHandlerAdapter {
@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
System.out.println(" 客户端连接打开");
}
@Override
public void sessionClosed(IoSession session) throws Exception {
super.sessionClosed(session);
System.out.println("客户端连接关闭");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
super.messageReceived(session, message);
// String msg = (String) message;
Message msg = (Message)message;
System.out.println(msg);
}
}
public class Message implements Serializable {
private String from;
private String to;
private String type;
private String info;
@Override
public String toString() {
return "Message{" +
"from='" + from + '\'' +
", to='" + to + '\'' +
", type='" + type + '\'' +
", info='" + info + '\'' +
'}';
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}