关于网络编程架构的初步学习,多线程编程。

本文深入探讨网络编程的基本架构,包括服务器端与客户端的创建流程、线程管理、通信协议和服务接口设计等内容。通过具体示例讲解如何实现文件上传下载及简单计算功能。
客户端:文件下载:
最好得列出在服务器中的文件,只有这样才能下载,用户不能凭空捏造文件。
客户端:文件上传:
如果文件与服务器的文件重名那怎么办?
解决方案:
1,不容许下载,只能修改文件名;
2,或则让该文件去代替源文件。
网络编程的一般架构:
服务器端的创建流程:
1.创建服务器的端口号:
   该过程主要是创建端口号的套接字;
2.创建该端口号的线程:
  A.我们引入线程池的概念,有多少socket的链接,我们就创建多少线程;    理由:如果来一个线程,我们就创建一个线程,那么导致服务器的响应速度会非常的慢。这就好比酒店的门童,如果门口来一个客户,我们就招聘一个服务员,那么将导致服务过程会相当的慢。换一种方式:何不事先就就招聘一堆服务员呢?这就是线程池的引入模型。当然如果线程初始化时创建太多也会有麻烦,他会占用太多的内存空间,对性能影响不能小觑。所以必须有量的制约。)
  B.线程的主要功能。
   首先在线程中我们必须找到套接字和通信协议;很显然这是该线程的私有变量。在run函数中主要就是进行service服务功能。
   在这里我们就不得不介绍service服务接口。
   通信协议必须完成service接口的功能。通信协议的参数就是套接字。   
3.通信协议时已知的,将通信协议传入到该线程中。
   所谓的通信协议就是服务器所能完成的一般功能。
   这里就指真正的套接字服务程序。
客户端创建的一般架构:
   首先我们必须了解:对于用户来说,他只是关心他所要实现的功能,他没有必要去了解通行协议。在这个实例中我们创建了一个接口,在该接口里
有上传和下载功能。这也就是说,用户知道这个接口就足够了,其他的的什么都不用操心。
   那么由谁来完成这个接口呢?当然这就是我们程序猿的事。
   在这个实例里,完成接口的是RemoteCalc类。很显然参数就是客户端的套接字。在这个类里完成上传和下载功能的具体实现过程。
   具体客户端的创建流程:
1. 首先你给出你要连接的对象和端口号。这就是客户端的套接字。
2. 在RemoteCalc类里完成功能即可。
以下的是同样的模型用来完成简单的计算。
public interface Calc { // 非常简单的接口定义,Calc.java
public int add(int i, int j);


public int sub(int i, int j);

}

//最后,创建一个客户端调用主程序,为了比较,也调用了一个
//客户端的计算器的本地对象。
public class CalcClient { // CalcClient.java,客户端主程序
public static void main(String[] args) throws Exception {
Calc c1 = new CalcImpl(); // 客户端虚拟机内部的计算器对象
Calc c2 = new RemoteCalc("localhost", 4321); // 远程对象的本地代理
while(true)
{
System.out.println("call local object:");
System.out.println("5 + 6 = " + c1.add(5, 6));
System.out.println("11 - 5 = " + c1.sub(11, 5));
System.out.println("call remote object:");
System.out.println("5 + 6 = " + c2.add(5, 6));
System.out.println("11 - 5 = " + c2.sub(11, 5));
}
}
}

public class CalcImpl implements Calc { // CalcImpl.java,Calc接口的实现类
public int add(int i, int j) {
return i + j;
} // 注意:本类并没有成员数据


public int sub(int i, int j) {
return i - j;
} // 没有共享冲突这个现象


public static void main(String[] args) { // 完成对add,sub方法的测试
Calc c = new CalcImpl();
System.out.println("5 + 6 = " + c.add(5, 6));
System.out.println("11 - 5 = " + c.sub(11, 5));
}
}

import java.io.*;
import java.net.*;


public class CalcProtocol implements IOStrategy { // CalcProtocol.java

Calc c = new CalcImpl(); // 此语句如果转移到service方法中会如何?


public void service(Socket socket) { // 本例子中只有一个协议对象,那么
try { // 计算器对象也只有一个,多线程共享的。
// 如将服务器端的Calc对象的创建定义在方法内,会产生什么样的变化?
// Calc c = new CalcImpl();
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(
socket.getOutputStream());
int command = 0;
while (true) {
command = dis.readInt(); // 实际上,协议命令的数值
switch (command) { // 没有多大的意义
case 1: // 命令1映射到add方法
dos.writeInt(c.add(dis.readInt(), dis.readInt()));
dos.flush();
break;
case 2: // 命令2映射到sub方法
dos.writeInt(c.sub(dis.readInt(), dis.readInt()));
dos.flush();
break;
}
}
} catch (Exception e) {
System.out.println("client disconnected.");
}
}
}

public class CalcServer { // CalcServer.java,服务器主程序
public static void main(String[] args) {
new NwServer(4321, new ThreadSupport(new CalcProtocol()));
}
}

public interface IOStrategy { // IOStrategy.java
public void service(java.net.Socket socket);  //对传入的socket对象进行处理
}

//下面是修改后的线程类,该程序对同步控制,wait和notify方法的调用要求较高
import java.net.*;


public class IOThread2 extends Thread {
private Socket socket = null;
private IOStrategy ios = null;


public IOThread2(IOStrategy ios) { // 请比较上一节中的IOThread类的构造方法
this.ios = ios; // 有何不同?
}


public boolean isIdle() { // 如果socket变量为空,那么这个线程当然是空闲的
return socket == null;
}


public synchronized void setSocket(Socket socket) {
this.socket = socket; // 传递给这个阻塞的线程一个“任务”,并唤醒它。
notify();
}


public synchronized void run() { // 这个同步方法并不是保护什么共享数据,
while (true) { // 仅仅因为wait方法调用必须拥有对象锁
try {
wait(); // 进入线程体后,立刻进入阻塞,等待状态
ios.service(socket); // 被唤醒后,立刻开始执行服务协议
socket = null; // 服务结束后,立刻返回到空闲状态
} catch (Exception e) {
e.printStackTrace();
}
}
}
}



import java.net.*;


public class NwServer { // NwServer.java,负责接受连接请求,并将创建的Socket对象
// 通过IOStrategy接口传递给ThreadSupport对象
public NwServer(int port, IOStrategy ios) { // 这个方法将在主线程中执行
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("server is ready");
while (true) {
Socket socket = ss.accept(); // 负责接受连接请求,
ios.service(socket); // 将服务器端的socket对象传递给
} // ThreadSupport对象
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}

import java.io.*;
import java.net.*;


public class RemoteCalc implements Calc {
private DataInputStream dis = null;
private DataOutputStream dos = null;


public RemoteCalc(String host, int port) throws Exception {
Socket s = new Socket(host, port); // 这个Socket对象创建完毕后何时销毁?
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
}


public int add(int i, int j) {
try {
dos.writeInt(1); // 将加法操作映射成命令1,然后发送命令
dos.writeInt(i); // 发送加法操作第一个操作数
dos.writeInt(j); // 发送加法操作第二个操作数
dos.flush();
return dis.readInt();
} catch (Exception e) { // 将检查异常转换为运行异常并抛出
throw new ArithmeticException(e.getMessage());
}
}


public int sub(int i, int j) {
try {
dos.writeInt(2); // 将加法操作映射成命令2,然后发送命令
dos.writeInt(i); // 发送减法操作第一个操作数
dos.writeInt(j); // 发送减法操作第二个操作数
dos.flush();
return dis.readInt();
} catch (Exception e) {
throw new ArithmeticException(e.getMessage());
}
}
}

import java.util.*; //下面的程序可以替换ThreadSupport.java
import java.net.Socket;


public class ThreadPoolSupport implements IOStrategy { // ThreadPoolSupport.java
private ArrayList threads = new ArrayList();
private final int INIT_THREADS = 50;
private final int MAX_THREADS = 100;
private IOStrategy ios = null;


public ThreadPoolSupport(IOStrategy ios) { // 创建线程池
this.ios = ios;
for (int i = 0; i < INIT_THREADS; i++) {
IOThread2 t = new IOThread2(ios); // 传递协议对象,但是还没有socket
t.start(); // 启动线程,进入线程体后都是wait
threads.add(t);
}
try {
Thread.sleep(300);
} catch (Exception e) {
} // 等待线程池的线程都“运行”
}


public void service(Socket socket) { // 遍历线程池,找到一个空闲的线程,
IOThread2 t = null; // 把客户端交给“它”处理
boolean found = false;
for (int i = 0; i < threads.size(); i++) {
t = (IOThread2) threads.get(i);
if (t.isIdle()) {
found = true;
break;
}
}
if (!found) // 线程池中的线程都忙,没有办法了,只有创建
{ // 一个线程了,同时添加到线程池中。
t = new IOThread2(ios);
t.start();
try {
Thread.sleep(300);
} catch (Exception e) {
}
threads.add(t);
}
t.setSocket(socket); // 将服务器端的socket对象传递给这个空闲的线程
} // 让其开始执行协议,向客户端提供服务
}



   
   

   
   

内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;最后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值