Java第十二天笔记01——网络编程

1.Sockete原理

  • 是网络应用程序编程的接口和一种机制
  • 用套接字中的相关函数来建立连接和完成通信
  • Socket可以看成在两个程序进行通讯连接中的一个端点
     

2.基于TCP的Socket编程

利用TCP协议进行通信两个应用程序,有主从之分一个称为服务器程(Server),另外一个称为客户机程(Client)

 

(1)交互过程

  1. 服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接
  2. 客户端程序创建一个socket并请求与服务器建立连接
  3. 刚才建立了连接的两个socket在一个单独的线程上对话
  4. 服务器开始等待新的连接请求

(2)例子

Ⅰ.简单例子

 ①服务端

package com.server.cn;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author lqh 服务器
 */
public class Server {
	public static void main(String[] args) {
		Socket socket = null;
		ServerSocket ss = null;
		try {
			// 1.启动服务器
			ss = new ServerSocket(8888);
			System.out.println("服务器已启动......");

			// 2.等待客户端连接
			socket = ss.accept();// 阻塞式方法,直到客户端链接进来,后续代码才能继续执行
			System.out.println("有新的客户端连接进来......" + "\nIP地址:" + socket.getInetAddress() + ",端口号:" + socket.getPort());

			// 5.接受客户端发送的消息
			InputStream in = socket.getInputStream();// 字节流,一个字节一个字节读取
			InputStreamReader inReader = new InputStreamReader(in);// 字符流一个字符一个字符读取
			BufferedReader reader = new BufferedReader(inReader);// 字符流,一行一行读取数据
			String message = reader.readLine();
			System.out.println("客户端说:" + message);

			// 6.给客户端发送消息
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			writer.println("你好,我不在,请留言!!!");
			writer.flush();

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 8.关闭资源,释放资源
			try {
				if (socket != null) {
					// Closing this socket will also close the socket's
					// InputStream and OutputStream.
					socket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (ss != null) {
					// Closing this socket will also close the socket's
					// InputStream and OutputStream.
					ss.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

②客户端

package com.server.cn;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author lqh 客户端
 */
public class Client {
	public static void main(String[] args) {
		Socket socket = null;
		try {
			// 3.连接服务器
			socket = new Socket("localhost", 8888);
			// 等价于
			// Socket socket = new Socket("127.0.0.1", 8888);

			// 4.给服务器发送消息
			OutputStream out = socket.getOutputStream();// 字节输出流,只能一个字节一个字节输出数据
			OutputStreamWriter outWriter = new OutputStreamWriter(out);// 字符流,一个字符一个字符输出数据
			PrintWriter writer = new PrintWriter(outWriter);// 字符流,一行一行输出数据
			writer.println("你好,在吗?");
			writer.flush();

			// 7.接受服务器消息
			BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 字符流,一行一行读取数据
			String message = reader.readLine();
			System.out.println("服务端说:" + message);

		} catch (UnknownHostException e) {// 主机未知异常
			e.printStackTrace();
		} catch (IOException e) {// IO流异常
			e.printStackTrace();
		} finally {
			// 8.关闭资源,释放资源
			try {
				if (socket != null) {
					/*Closing this socket will also close the socket's InputStream and OutputStream.
					 * 所以不需要关闭输出流
					 */ 
					socket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

③运行结果

先打开服务端,再打开客户端

Ⅱ.服务端与客户端之间的聊天,当服务端输入“exit”时,结束对话

①服务端

package com.onetoone.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author lqh 实现客户端与服务器一对一循环聊天
 */
public class Server {
	public static void main(String[] args) {
		ServerSocket server = null;
		Socket socket = null;
		try {
			// 1.启动服务器
			server = new ServerSocket(8888);
			System.out.println("服务端开启中。。。");
			// 2.等待客户端连接
			socket = server.accept();

			BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			Scanner scanner = new Scanner(System.in);

			outer:while (true) {
				// 5.接受客户端发送的信息
				String message = reader.readLine();

				// 判断客户端是否下线
				if ("exit".equals(message.trim())) {
					System.out.println("IP地址为:" + socket.getInetAddress() + ", 端口号为:" + socket.getPort() + "的客户端已下线!");
					break outer;
				} else {
					System.out.println("客户端说:" + message);
				}
				// 6.给客户端发送消息
				System.out.println("服务端,请输入:");
				String text = scanner.nextLine();
				writer.println(text);
				writer.flush();
			}

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 8.关闭资源、释放资源
			if (socket != null) {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (server != null) {
				try {
					server.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

②客户端

package com.onetoone.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client {
	public static void main(String[] args) {
		Socket client = null;
		try {
			// 3.连接服务器
			client = new Socket("localhost", 8888);
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
			BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			Scanner scanner = new Scanner(System.in);
			outer:while (true) {
				// 4.给服务器发送消息
				System.out.println("客户端,请输入:");
				String text = scanner.nextLine();
				// 判断如果客户端输入"exit",表客户端准备退出
				writer.println(text);
				writer.flush();
				if ("exit".equals(text)) {
					break outer;
				}

				// 7.接收服务器消息
				String message = reader.readLine();
				System.out.println("服务端说:" + message);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 8.关闭资源、释放资源
			if (client != null) {
				try {
					client.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

③运行结果

Ⅲ.服务端与服务端之间的聊天

①服务端

package com.clientonetomore.test2;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

/**
 * @author lqh 实现客户端循环聊天群聊,改进版
 */
public class Server {

	// 用于保存所有客户端聊天的socket对象
	static HashMap<Integer, Socket> socketMap = new HashMap<>();

	public static void main(String[] args) {
		ServerSocket server = null;
		Socket socket = null;
		try {
			// 1.启动服务端
			server = new ServerSocket(8888);
			System.out.println("服务端开启...");

			// 2.等待客户端连接
			int num = 0;
			while (true) {
				socket = server.accept();
				System.out.println(socket.getPort() + "客户端连接成功!");
				socketMap.put(num++, socket);
				ServerThread t = new ServerThread(socket);
				t.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 8.关闭资源、释放资源
			if (socket != null) {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (server != null) {
				try {
					server.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

②客户端

package com.clientonetomore.test2;

import java.io.IOException;
import java.net.Socket;

public class Client {
	public static void main(String[] args) {
		Socket client = null;
		try {
			// 3.连接服务端
			client = new Socket("localhost", 8888);

			// 4.给其它客户端发送消息
			new Client_sendThread(client).start();

			// 7.接收其它客户端发来的消息
			new Client_getThread(client).start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

③服务端接收并转发信息的线程

package com.clientonetomore.test2;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;

public class ServerThread extends Thread {
	private Socket socket;

	public ServerThread(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

			while (true) {
				// 5.接受客户端发送的信息
				String message = reader.readLine();
				System.out.println("客户端说:" + message);

				// 给所有客户端转发收到的消息
				HashMap<Integer, Socket> socketMap = Server.socketMap;
				Collection<Socket> values = socketMap.values();
				for (Socket socket : values) {
					// 自己不用收到自己的消息
					if (!this.socket.equals(socket)) {
						PrintWriter clientWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
						clientWriter.println(message);
						clientWriter.flush();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

④客户端发送信息的线程

package com.clientonetomore.test2;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client_sendThread extends Thread {
	private Socket socket;

	public Client_sendThread(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		PrintWriter writer;
		try {
			writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			Scanner scanner = new Scanner(System.in);
			while (true) {
				// 给其它客户端发送消息
				System.out.println("客户端,请输入:");
				String text = scanner.nextLine();
				// 判断如果客户端输入"exit",表客户端准备退出
				writer.println(text);
				writer.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

⑤客户端接收信息的线程

package com.clientonetomore.test2;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client_sendThread extends Thread {
	private Socket socket;

	public Client_sendThread(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		PrintWriter writer;
		try {
			writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			Scanner scanner = new Scanner(System.in);
			while (true) {
				// 给其它客户端发送消息
				System.out.println("客户端,请输入:");
				String text = scanner.nextLine();
				// 判断如果客户端输入"exit",表客户端准备退出
				writer.println(text);
				writer.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

⑥运行效果

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值