Java网络编程
-
网络编程:指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。
URL处理:http://www.baidu.com/search?code=Android&type=1
- URL(Uniform Resource Locator)中文名为统一资源定位符,有时也被俗称为网页地址。
- http/https :传输协议 TCP/IP协议
- www.baidu.com :域名表示一台网络中的电脑
(ipv4 ipv6 )IP地址:唯一标识一台网络中的计算机
32位:4个部分 每部分8个字节- DNS服务器:域名解析 将www.baidu.com的域名解析为对应的IP地址
- search:对应的后天程序文件 php java jsp
- ? 表示运行这个程序需要传递的参数
- code=Android code是服务器端规定的字段
- & 如果有多个参数使用&连接
ps:查找自己的电脑IP:win+R进入DOS窗口输入ifconfig即可
-
数据传输主要通过TCP/IP协议,以下是两种常见的协议:
-
TCP(安全):TCP 是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
-
UDP(不安全,但是快):UDP 是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据包。
-
Socket 编程
相关概念
-
IP地址:唯一标识某一台电脑
-
端口号:唯一标识电脑上的某一个进程(程序)80
-
Socket类:客户端 手机应用、浏览器等
-
ServerSocket:服务器端 存储、处理数据

使用方法:
- 读取数据:客户端读取 服务器端读取
BufferedReader->InputStreamReader->socket.getInputStream() - 读取终端
BufferedReader->InputStreamReader->System.in - 输出:客户端输出 服务器端输出
BufferedWriter->OutputStreamWriter->serverSocket.getOutputStream()
PrintStream(socket.getOutputStream)
1. 实现客户端和服务器端传递数据(注意端⼝号必须相同 先运⾏Server 再运⾏Client)
客户端:(1)创建用于通信的Socket,指明IP地址与端口号。
(2)使用BufferedReader用循环接收服务器端的数据。
(3)使用PrintStream向服务器端发送数据,并告诉发送完成socket.shutdownOutput()。
服务器端:(1)创建服务器端的ServerSocket,并指明端口。
(2)用serverSocket.accept()获取连接客户端的socket。
(3)用PrintStream向客户端发送数据,完成时使用serverSocket.shutdownOutput()
(4)使用BufferedReader接收客户端发来的数据
模拟客户端:
//模拟客户端
//10.129.49.204
class Client{
public static void main(String[] args) throws IOException {
// 1.创建用于通信的Socket
// 指明和谁通信:IP地址 端口号
Socket socket = new Socket("10.129.25.52",8989);
//接收服务器端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 向服务器端发送数据
// socket.getOutputStream();
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//客户端向服务器端发送数据
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好啊!!!");
socket.shutdownOutput();
}
}
模拟服务器端:
class Server{
public static void main(String[] args) throws IOException {
//1.创建服务器的serversocket
ServerSocket ss = new ServerSocket(8989);
//2.获取连接的客户端的socket
Socket clientSocket = ss.accept();
//3.向客户端发送数据
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登录成功");
//输出完毕
clientSocket.shutdownOutput();
// 4.接收客户端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
2. 手动输入内容发送,将输⼊的内容发送给客户端 可以⼀直发
异常处理:如果出现异常,按从小到大关闭资源
两种方式处理异常:
- 方式1使用if判断语句
Socket socket = null;
try {
socket = new Socket("10.129.49.204",8888);
//接收服务器端信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错,请重新登录");
}finally {
// 关闭连接
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 方式2
try( ServerSocket serverSocket = new ServerSocket(8888)) {
// 监听客户端
Socket socket = serverSocket.accept();
// 从终端接收数据发送给客户端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//获取向客户端输出数据的输出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
// 发送给客户端
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
class MyClient{
public static void main(String[] args){
//连接服务器端的socket
Socket socket = null;
try {
socket = new Socket("10.129.49.204",8888);
//接收服务器端信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错,请重新登录");
}finally {
// 关闭连接
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class MyServer{
public static void main(String[] args){
//创建ServerSocket 自动关闭
try( ServerSocket serverSocket = new ServerSocket(8888)) {
// 监听客户端
Socket socket = serverSocket.accept();
// 从终端接收数据发送给客户端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//获取向客户端输出数据的输出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
// 发送给客户端
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 实现客户端向服务器端上传图⽚(字节流)
class Client{
public static void main(String[] args) throws IOException {
//链接服务器端 获取socket
Socket socket = new Socket("10.129.49.204",8080);
//创建服务器端对应的输入流 用于接受服务器端发来的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println( bufferedReader.readLine());
//向服务器端发送文件(图片)
String path = "C:\\Users\\gyl\\Desktop\\1.jpg";
//1. 将文件写入到内存
FileInputStream fis = new FileInputStream(path);
// 2 .创建字节流 outputStream
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[1024];
int length = -1;
while ((length = fis.read(buffer)) != -1){
bos.write(buffer,0,length);
}
socket.shutdownOutput();
}
}
class Server{
public static void main(String[] args) throws IOException {
//创建服务器的serverSocket
ServerSocket serverSocket = new ServerSocket(8080);
//监听客户端连接
//当有客户端来连接这个服务器 就可以得到对应的socket
//当没有客户端来连接 服务器一直在这里等待
Socket socket = serverSocket.accept();
//创建客户端对应的输出流对象 用于向这个客户端发送数据
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("连接成功 可以发送数据了");
// 接收客户端传递过来的图片
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//文件对应的输出流
String path = "D:\\AndroidStudioProjects\\JavaCourse\\Java\\src\\main\\java\\day12\\media\\1.jpg";
FileOutputStream fos = new FileOutputStream(path);
byte[] buffer = new byte[1024];
int length = -1;
while ((length = bis.read(buffer)) != -1){
fos.write(buffer,0,length);
}
}
}
4.使⽤多线程实现对聊
- 创建一个类实现Runnable接口,重写run方法
- 创建一个类继承于Thread类,重写run方法
/**
* 客户端和服务器端可以随意的发送内容
* 从终端输入
*
* 客户端:
* 主线程:接收终端输入 将终端的输入发送给服务器端
* 子线程:接收服务器端发送过来的数据
* 服务器端:
* 主线程:接收终端输入 将终端的输入发送给客户端
* 子线程:接收客户端发送过来的数据
*/
class Cilent{
public static void main(String[] args) throws IOException {
//链接服务器端 获取socket
Socket socket = new Socket("10.129.49.204",8888);
// 用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
// 主线程处理终端输入发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**
* 创建一个子线程 处理客户端接收服务器的数据
*/
class ClientThread implements Runnable{
private Socket socket;
// 保存socket对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
// 获取服务器端的输入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
// 出现异常 关闭资源 从小到大
try {
if (br != null){
br.close();
}
if (socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Server{
public static void main(String[] args) throws IOException {
// 创建服务器端
ServerSocket ss = new ServerSocket(8888);
// 获取客户端的socket
Socket socket = ss.accept();
// 创建子线程 处理客户端输入信息
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
// 客户端输出流对象
PrintStream ps = new PrintStream(socket.getOutputStream());
// 读取终端的输入 将输入输出给客户端
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的书据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
// 关闭输入输出流
// 关闭对应的socket链接
try {
if (br != null) {
br.close();
}
if (socket != null) {
socket.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
5.实现群聊
- 使用ArrayList 保存每一个连接到的客户端,并且通过循环依次将信息发送给每一个客户端。
class Server{
// 保存每一个链接过来的对象
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8888);
//不停地等待客户端来连接
while (true){
Socket socket = ss.accept();
// 当有客户端连接过来了就保存
sockets.add(socket);
//开启一个线程处理每个客户端的输入
new ServerThread(socket).start();
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的书据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
// 群发消息
// 遍历Server维护的数组
for (Socket socket:Server.sockets){
// 想socket对应的客户端发送信息
PrintStream s = new PrintStream(socket.getOutputStream());
s.println(line);
}
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
// 关闭输入输出流
// 关闭对应的socket链接
try {
if (br != null) {
br.close();
}
if (socket != null) {
socket.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
class Cilent{
public static void main(String[] args) throws IOException {
//链接服务器端 获取socket
Socket socket = new Socket("10.129.49.204",8888);
// 用一个子线程处理服务器端的数据
new Thread(new ClientThread(socket)).start();
// 主线程处理终端输入发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**
* 创建一个子线程 处理客户端接收服务器的数据
*/
class ClientThread implements Runnable{
private Socket socket;
// 保存socket对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
// 获取服务器端的输入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
// 出现异常 关闭资源 从小到大
try {
if (br != null){
br.close();
}
if (socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
心得体会
关于客户端和服务器端的操作,刚开始对于输入输出有点绕,不过多写了几遍之后,就更清楚了 ,类似于模板。同时又将多线程的知识融入进来,对知识的理解也更加深刻了。
网友评论