学习网络通信也有一段时间了,期间也有许多理解与感悟。现在写出来和大家一起分享,交流。废话不多说,开始进入正题。
首先说一下通信的流程。通信有几个重要的东西。首先是服务器的程序Server。他调用ServerSocket的accept方法,在该端口相当于设置一个监听器,监听是否有网络连接请求发送过来。第二个就是客户端的访问请求和交流线程ClientThread。他也通过一个socket连接上服务器,此时服务器收到一个请求,便自身生成一个Server线程来处理该请求(这个需要自己定义与构思)。最后,服务器和客户端就通过这两个线程来交流。其实可以将这两个线程看成一个整体(个人认为),只是将他们分在两台不同的电脑上,其实他们的实现的功能是类似的。
流程图如下 :
现在开始来做基本的构架了。我先将自己实现的图片发上几张。
-------打开服务端
打开登录界面(在同一台电脑上测试)
都登陆上
群发和私聊,这里要注意用户选择框的初始化,以及每个用户上线和下线后,要进行删除该用户和添加该用户的操作
退出之后,给每个客户端发送一个消息
这个是输错用户名或输错密码或者输入了以及登录的用户的信息后出现的状况\
这个是在我关掉服务器之后,用户登录连接不上弹出的对话框
下面开始聊代码的实现和重点要注意的地方,最后会贴出完整代码。
1.server
public void seekClient(int port) throws IOException{ ServerSocket ss = new ServerSocket(port); while(true){ Socket sc = ss.accept(); new ServerThread(sc).start();//交给线程处理 } }
每接到一个请求就生成一个对应的ServerThread来处理该请求
2.ClientThread
public void run(){ try { //!步骤一 : 发送请求 sc = new Socket("localhost", port); InputStream ins = sc.getInputStream(); OutputStream out = sc.getOutputStream(); reader = new BufferedReader(new InputStreamReader(ins,"gb2312")); writer = new BufferedWriter(new OutputStreamWriter(out,"gb2312")); //!步骤二:登录验证 login(); while(LoginWords.equals("Can't")){//无法登陆 JOptionPane.showMessageDialog(UI, "用户不存在或密码错误或用户已登录!"); login(); } String msg; if(LoginWords.equals("Can")){ System.out.println("Login successfully..."); //!步骤三 : 登录成功后生成聊天界面,因要通过Client线程进行交流,故将该线程传给聊天界面 UI.dispose(); ChatUI ct = new ChatUI(this); ct.init(); while(doing){//登陆成功,显示聊天界面 msg = reader.readLine(); if(msg.equals(connect.Cons.addConnectUserCmmd)){//添加用户选择项 if(jcb != null){//添加 msg = reader.readLine();//这个怎么会发出来? jcb.addItem(msg); } }else if(msg.equals(connect.Cons.deleteConnectUserCmmd)){//删除用户选择项 if(jcb != null){//添加 msg = reader.readLine(); jcb.removeItem(msg); } }else{ ct.addMsg(msg); } } }else{ System.out.println("LoginWords = "+LoginWords); } sc.close(); System.out.println(username+"在客户端退出"); } catch (IOException e) { // e.printStackTrace(); //连接不上,返回登录界面,并弹出提示窗口 JOptionPane.showMessageDialog(UI, "服务器无响应..."); } }
这是主要的登录步骤,里面的每个登录以及发送消息的方法可以自己定义(要注意的是)线程结束时要调用该Socket的close()方法,发送消息时,输出流输出后要调用一下flush方法
3.ServerThread
public void run(){ try { InputStream ins = sc.getInputStream(); OutputStream out = sc.getOutputStream(); //将输入流和输出流封装 reader = new BufferedReader(new InputStreamReader(ins,"gb2312")); writer = new BufferedWriter(new OutputStreamWriter(out,"gb2312")); username = reader.readLine(); String psd = reader.readLine(); System.out.println("username : "+username); System.out.println("password : "+psd); loginable = checkPsd(username,psd); if(!loginable){//未登陆上,给客户端发送一个信号 writer.write("Can't"+"\r\n"); writer.flush(); return; }else{ writer.write("Can"+"\r\n"); writer.flush(); } //将本线程加入到集合线程中,将登录状态设为true ThreadCollection.addClient(this); DBtools.setLogin(username, true); String msg; try{ msg = reader.readLine();//客户端退出时报异常 while(msg != null){ //得到信息,处理信息(这里即将信息发给所有在线的用户客户端) if(msg.equals(connect.Cons.setConnectCmmd)){//设置用户的命令 msg = reader.readLine();//放弃此条命令的发送 connect2username = msg; }else{ if(connect2username.equals( "All")){//默认发给所有用户 ThreadCollection.sendAllMsg(username+" : "+msg); }else{ ThreadCollection.sendMsg(connect2username, username+"[私] : "+msg); //要給自己也發一個信息 ThreadCollection.sendMsg(username, username+" : "+msg+"[自-> "+connect2username+"]");//沒發出來? } } msg = reader.readLine();//客户端退出时报异常 } }catch(Exception ex){ } //将该用户登陆状态设置为false,并在集合中删除该线程 ThreadCollection.deleteClient(username); DBtools.setLogin(username, false); sc.close(); System.out.println(username+"在服务端退出"); System.out.println(username+" -> 状态 : "+DBtools.getLogin(username)); ThreadCollection.sendAllMsg("******"+username+"已经退出...**********"); } catch (IOException e) { e.printStackTrace(); } }
这里的要点是,因为两个线程之间是通过输入流和输出流通信的,所以要确认是否登录就要自己定义一下登录的格式。我的代码就是这样实现:客户端线程发过来 用户名 、密码,服务端线程接收到,调用一下数据库(这里我是自己定义的)的数据,然后返回一个登陆成功或失败的信息。客户端接收到这个信息决定是否能登陆进行聊天,该线程要不要进行下去。
4.数据库DBtools,自己定义用户名等属性的一个类,可以用数据库代替
public static ArrayList<User> users = new ArrayList<User>(); static{ users.add(new User("aa","123",false)); users.add(new User("bb","123",false)); users.add(new User("cc","123",false)); }
因为要调用里面的信息,所以要自己定义几个static方法。上述代码中的User是我自己定义的类,可以将个人信息封装在里面,false代表未登录。
5.服务端线程集合,用户登陆后,将该线程加入;用户退出后,将该对应线程删除。
private static ArrayList<ServerThread> list = new ArrayList<ServerThread>();
用一个static集合就行,自己定义调用方法,大概有以下几个
因为上面的操作都要调用一个方法,那就是查找用户(根据用户名),那么可以把这个方法写出来,上述直接调用
private static ServerThread findServer(String name){ ServerThread st; for(int i = 0 ; i < list.size() ; i++ ){ st = list.get(i) ; if(st.getUsername().equals(name)){//找到用户 return st; } } return null; }
6.聊天界面ChatUI,自己定义,注意输入框和输出框的信息都要和服务端交流,所以将客户端线程传入作为内部成员
public ChatUI(ClientThread ct){ this.ct = ct; if(username == null && ct != null) username = ct.getUsername(); }
7.登陆界面,最后我们可以制作一个登录界面来传递用户名密码等。由登陆界面生成客户端线程来发送请求
public void init(){ this.setTitle("登陆界面"); this.setBounds(400,400,200,180); this.setDefaultCloseOperation(3); this.setResizable(false); this.setLayout(new FlowLayout()); JLabel jl = new JLabel("用户名 :"); jtf = new JTextField(12); JLabel jl1 = new JLabel("密 码 :"); psd = new JPasswordField(12); JButton jb = new JButton("登 陆"); JComponent jc[] = {jl,jtf,jl1,psd,jb}; for(int i = 0;i < jc.length;i++){ this.add(jc[i]); } this.setVisible(true); jb.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { new ClientThread(8888,jtf.getText(),new String(psd.getPassword()),ClientUI.this).start(); } }); }
好了,主要的思路都讲完了。如果你也想做网络通信但是感到困惑,希望上面我的思路能帮到你,下面是完整的代码:(如果你觉得我做的有缺陷,欢迎和我进行交流)
package client; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPasswordField; import javax.swing.JTextField; /** * 登录界面 * @author 姜鑫 * */ public class ClientUI extends JFrame{ private JTextField jtf; private JPasswordField psd; public static void main(String []args){ new ClientUI().init(); } public void init(){ this.setTitle("登陆界面"); this.setBounds(400,400,200,180); this.setDefaultCloseOperation(3); this.setResizable(false); this.setLayout(new FlowLayout()); JLabel jl = new JLabel("用户名 :"); jtf = new JTextField(12); JLabel jl1 = new JLabel("密 码 :"); psd = new JPasswordField(12); JButton jb = new JButton("登 陆"); JComponent jc[] = {jl,jtf,jl1,psd,jb}; for(int i = 0;i < jc.length;i++){ this.add(jc[i]); } this.setVisible(true); jb.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { new ClientThread(8888,jtf.getText(),new String(psd.getPassword()),ClientUI.this).start(); } }); } }
package client; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import javax.swing.JComboBox; import javax.swing.JOptionPane; /** * 客户端线程 * @author 姜鑫 * */ public class ClientThread extends Thread{ private String username; private String password; private int port; private Socket sc; private BufferedReader reader; private BufferedWriter writer; private ClientUI UI; private String LoginWords ; private boolean doing = true; private JComboBox jcb = null; public void setJCB(JComboBox jcb){ this.jcb = jcb; } public ClientThread(int port,String username,String password,ClientUI UI){ this.port = port; this.username = username; this.password = password; this.UI = UI; } public String getUsername(){ return username; } public void run(){ try { sc = new Socket("localhost", port);//发送请求 InputStream ins = sc.getInputStream(); OutputStream out = sc.getOutputStream(); reader = new BufferedReader(new InputStreamReader(ins,"gb2312")); writer = new BufferedWriter(new OutputStreamWriter(out,"gb2312")); login(); while(LoginWords.equals("Can't")){//无法登陆 JOptionPane.showMessageDialog(UI, "用户不存在或密码错误或用户已登录!"); login(); } String msg; if(LoginWords.equals("Can")){ System.out.println("Login successfully..."); UI.dispose(); ChatUI ct = new ChatUI(this); ct.init(); while(doing){//登陆成功,显示聊天界面 msg = reader.readLine(); if(msg.equals(connect.Cons.addConnectUserCmmd)){//添加用户选择项 if(jcb != null){//添加 msg = reader.readLine();//这个怎么会发出来? jcb.addItem(msg); } }else if(msg.equals(connect.Cons.deleteConnectUserCmmd)){//删除用户选择项 if(jcb != null){//添加 msg = reader.readLine();//这个怎么会发出来? jcb.removeItem(msg); } }else{ ct.addMsg(msg); } } }else{ System.out.println("LoginWords = "+LoginWords); } sc.close(); System.out.println(username+"在客户端退出"); } catch (IOException e) { // e.printStackTrace(); //连接不上,返回登录界面,并弹出提示窗口 JOptionPane.showMessageDialog(UI, "服务器无响应..."); } } public void login(){ try { //发送登录信息 writer.write(username+"\r\n"); writer.write(password+"\r\n"); writer.flush(); LoginWords = reader.readLine(); } catch (IOException e) { e.printStackTrace(); } } public void sendMsg(String msg) throws IOException{ writer.write(msg+"\r\n"); writer.flush(); } public void close() throws IOException{//关闭线程 doing = false; } }
package client; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.IOException; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class ChatUI extends JFrame implements WindowListener{ private JTextArea print ; private JTextArea write; private ClientThread ct; private String username; // public static void main(String[]args){ // new ChatUI(null).init(); // } public ChatUI(ClientThread ct){ this.ct = ct; if(username == null && ct != null) username = ct.getUsername(); } public void init(){ this.setTitle("我们的小天地..."); this.setBounds(400, 400, 350, 260); this.setDefaultCloseOperation(3); this.setResizable(false); this.setLayout(new FlowLayout(0,10,1)); print = new JTextArea(); print.setFocusable(false);//输出框无法聚焦 print.setLineWrap(true);//自动换行 JScrollPane jsp = new JScrollPane(print); jsp.setPreferredSize(new Dimension(240,180)); JLabel jl1 = new JLabel("I am : "+ username); write = new JTextArea(); write.setLineWrap(true); JScrollPane jsp1 = new JScrollPane(write); jsp1.setPreferredSize(new Dimension(100,40)); JButton jb = new JButton("发送消息"); String str[] = {"All"}; JComboBox select2chatUser = new JComboBox(str); JLabel jl2 = new JLabel("talk to : "+(String)select2chatUser.getSelectedItem()); // print.set//设置为自动换行 // this.add(print); this.add(jsp); this.add(jl1); this.add(jl2); // this.add(write); this.add(jsp1); this.add(select2chatUser); this.add(jb); this.setVisible(true); ct.setJCB(select2chatUser); select2chatUser.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { //得到选中的项,即要连接的用户 JComboBox jcb = (JComboBox)e.getSource(); String s = (String)jcb.getSelectedItem();//得到用户名 try { ct.sendMsg(connect.Cons.setConnectCmmd); ct.sendMsg(s); } catch (IOException e1) { e1.printStackTrace(); }//发送连接请求 } }); jb.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { //发送消息 try { ct.sendMsg(write.getText()); write.setText(null);//输出一个语句后,清空输入框 } catch (IOException e1) { e1.printStackTrace(); } } }); } public void addMsg(String Msg){ print.append(Msg+"\r\n"); } @Override public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { try { ct.close(); } catch (IOException e1) { e1.printStackTrace(); } } @Override public void windowClosed(WindowEvent e) { try { ct.close(); } catch (IOException e1) { e1.printStackTrace(); } } @Override public void windowIconified(WindowEvent e) { // TODO Auto-generated method stub } @Override public void windowDeiconified(WindowEvent e) { // TODO Auto-generated method stub } @Override public void windowActivated(WindowEvent e) { // TODO Auto-generated method stub } @Override public void windowDeactivated(WindowEvent e) { // TODO Auto-generated method stub } }
package server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 服务端 * @author 姜鑫 * */ public class ServerListener { public static void main(String[]args) throws IOException{ new ServerListener().seekClient(8888); } public void seekClient(int port) throws IOException{ ServerSocket ss = new ServerSocket(port); while(true){ Socket sc = ss.accept(); new ServerThread(sc).start();//交给线程处理 } } }
package server; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.SocketException; import connect.DBtools; import connect.ThreadCollection; /** * 服务端得到一个客户端的请求时,生成此线程 * @author 姜鑫 * */ public class ServerThread extends Thread{ private Socket sc; private BufferedReader reader ; private BufferedWriter writer ; private boolean loginable = false; private String username; private String connect2username; public ServerThread(Socket sc){ this.sc = sc; connect2username = "All"; } public void run(){ try { InputStream ins = sc.getInputStream(); OutputStream out = sc.getOutputStream(); //将输入流和输出流封装 reader = new BufferedReader(new InputStreamReader(ins,"gb2312")); writer = new BufferedWriter(new OutputStreamWriter(out,"gb2312")); username = reader.readLine(); String psd = reader.readLine(); System.out.println("username : "+username); System.out.println("password : "+psd); loginable = checkPsd(username,psd); if(!loginable){//未登陆上,给客户端发送一个信号 writer.write("Can't"+"\r\n"); writer.flush(); return; }else{ writer.write("Can"+"\r\n"); writer.flush(); } //将本线程加入到集合线程中,将登录状态设为true ThreadCollection.addClient(this); DBtools.setLogin(username, true); String msg; try{ msg = reader.readLine();//客户端退出时报异常 while(msg != null){ //得到信息,处理信息(这里即将信息发给所有在线的用户客户端) if(msg.equals(connect.Cons.setConnectCmmd)){//设置用户的命令 msg = reader.readLine();//放弃此条命令的发送 connect2username = msg; }else{ if(connect2username.equals( "All")){//默认发给所有用户 ThreadCollection.sendAllMsg(username+" : "+msg); }else{ ThreadCollection.sendMsg(connect2username, username+"[私] : "+msg); //要給自己也發一個信息 ThreadCollection.sendMsg(username, username+" : "+msg+"[自-> "+connect2username+"]");//沒發出來? } } msg = reader.readLine();//客户端退出时报异常 } }catch(Exception ex){ // ex.printStackTrace(); // System.out.println("该问题正待解决"); } //将该用户登陆状态设置为false,并在集合中删除该线程 ThreadCollection.deleteClient(username); DBtools.setLogin(username, false); sc.close(); System.out.println(username+"在服务端退出"); System.out.println(username+" -> 状态 : "+DBtools.getLogin(username)); ThreadCollection.sendAllMsg("******"+username+"已经退出...**********"); } catch (IOException e) { e.printStackTrace(); } } private boolean checkPsd(String name,String psd){//核对密码 String truePsd = DBtools.getPsd(name); if(truePsd == null || !truePsd.equals(psd) || DBtools.getLogin(name)) return false; else return true; } public String getUsername(){ return username; } public void sendMsg2one(String msg) throws IOException{//向所有用户发送消息 writer.write(msg+"\r\n"); writer.flush(); } }
package connect; import java.util.ArrayList; /** * 库,存储可用用户的信息 * @author 姜鑫 * */ public class DBtools { //哈希表 public static ArrayList<User> users = new ArrayList<User>(); static{ users.add(new User("aa","123",false)); users.add(new User("bb","123",false)); users.add(new User("cc","123",false)); } public static String getPsd(String user){//得到密码 User u = findUser(user); if(u != null){ return u.password; }else{ return null; } } public static void setLogin(String user,boolean login){//设置登陆状态 User u = findUser(user); u.isLogin = login; } public static boolean getLogin(String name){//获得登录状态 User u = findUser(name); return u.isLogin; } private static User findUser(String name){ for(User u : users){ if(u.name.equals(name)) return u; } return null; } } class User{ String name; String password; boolean isLogin; public User(String name , String password ,boolean isLogin) { this.name = name; this.password = password; this.isLogin = isLogin; } }
package connect; import java.io.IOException; import java.util.ArrayList; import server.ServerThread; /** * server线程的集合 * @author 姜鑫 * */ public class ThreadCollection { private static ArrayList<ServerThread> list = new ArrayList<ServerThread>(); //添加用户 public static void addClient(ServerThread ct) throws IOException{ //添加用户前,该用户的名称要显示在客户端的选择框中 //给所有其他用户添加一个选择项 String name = ct.getUsername(); sendAllMsg(connect.Cons.addConnectUserCmmd); sendAllMsg(name); //添加此用户,并初始化他的客户端选择框 list.add(ct); for(ServerThread st : list){ if(st == ct)//排除自身 continue; sendMsg(name,connect.Cons.addConnectUserCmmd); sendMsg(name,st.getUsername()); } } //删除用户 public static boolean deleteClient(String clientName) throws IOException{ boolean bool = false; //删除该用户 ServerThread st = findServer(clientName); list.remove(st); //在所有用户的选择框中删除该用户 sendAllMsg(connect.Cons.deleteConnectUserCmmd); sendAllMsg(clientName); return bool; } //向全体用户发送消息 public static void sendAllMsg(String msg) throws IOException{ for(ServerThread st : list){ st.sendMsg2one(msg); } } public static void sendMsg(String username,String msg) throws IOException{ //给某个用户发送消息 ServerThread st = findServer(username); if(st == null) return; st.sendMsg2one(msg); } private static ServerThread findServer(String name){ ServerThread st; for(int i = 0 ; i < list.size() ; i++ ){ st = list.get(i) ; if(st.getUsername().equals(name)){//找到用户 return st; } } return null; } }
package connect; /** * 固定的发送消息的语法 * @author 姜鑫 * */ public interface Cons { //设置连接某个或者所有用户的命令,与连接用户的名字相配对 String setConnectCmmd = "command@connect2";//用户请求 String addConnectUserCmmd = "command@addCntUser";//服务器要求 String deleteConnectUserCmmd = "command@deleteCntUser";//服务器要求 String Commands[] = {setConnectCmmd,addConnectUserCmmd}; }
相关推荐
充电网络的建设不仅需要硬件设施,还需要软件支持,如充电服务平台的搭建,可以实现充电预约、支付、状态查询等功能,提升用户的充电体验。此外,智能电网技术的应用也使得充电网络能够更好地融入电网系统,平衡电力...
这样的网络设计需要实现包括教师备课授课、学生学习交流、校内信息公告、远程电子通讯、Internet通讯浏览等基本功能。设计者需要充分考虑网络的实用性、可靠性和扩展性。 为了实现上述设计目标,我们利用模拟仿真...
校园计算机网络设计方案旨在构建一个覆盖全校范围的网络系统,以满足教学、管理以及信息交流的需求。以下是该设计方案的关键点: **一、网络设计原则与需求分析** 1. **资源共享**:校园网络应能实现学校内部资源的...
本文将深入探讨"网络游戏-基于语音控制网络的实现方法、装置、系统及存储介质"这一主题,详细介绍其背后的技术原理、应用优势以及实现过程。 一、语音识别技术基础 语音控制网络的关键在于语音识别技术。这项技术...
通过本项目的实施,可以深入了解Winsock控件的基本属性、方法和事件,理解网络聊天通信的概念,掌握如何使用传输控制协议(TCP)进行数据交换,以及初步学会网络聊天程序的设计和开发方法。 ### 二、相关知识 ####...
标题中的“TCP完全端口技术实现网络聊天服务器”是指通过TCP协议来建立一个可以支持多用户实时交流的网络聊天平台。TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它能确保数据在...
其中,NSA架构相较于SA架构来说,能够在短时间内实现5G服务的初步覆盖,而SA架构则提供了更全面、更高质量的服务体验。目前,网络架构正随着5G标准的进展逐步完善。 #### Massive MIMO关键技术 Massive MIMO(大...
计算机网络是现代社会信息流通的重要基础设施,它将地理上分散的计算机系统通过通信设备连接起来,使它们能够在遵循网络协议的基础上实现数据交换和资源共享。本教程旨在为初学者提供计算机网络的基础知识,帮助他们...
校园网内用户可以享受到智能化的六大功能,即网络化教育、电脑购物、数字化娱乐、电脑阅读、电子邮件帮助亲友交流和初步实现家庭上班。 因此,在学校内进行信息化建设,兴建计算机网络,是当今的趋势,计算机网络...
* 第一期工程:初步建立校园网络中心,整个校园布点 108 点,各教室、专用教室、会议室等均预留接口,通过网通专线接入教育网和 Internet(国际互连网)。 * 第二期工程:为各办公室、专用教学等增配电脑,实现校园...
- **Internet的崛起**:随着Internet的全球普及,计算机网络进入了全新的发展阶段,实现了全球范围内的信息共享和交流。 #### 二、计算机网络的定义与组成 **定义**:计算机网络是一系列独立自治的计算机通过网络...
其实质在于要求网络用户在进行在线活动时使用真实身份信息进行注册,以此作为参与网络交流的基础条件。 **意义:** 1. **维护网络秩序**:通过实施网络实名制,可以有效地防止网络上的虚假信息传播、恶意攻击和...
- **Internet**:是一个基于TCP/IP协议的全球性计算机网络,将世界各地的不同计算机网络互连在一起,实现资源共享和信息交流。 - **典型应用**:包括信息浏览(Web服务)、电子邮件(E-MAIL)、文件传输(FTP)和...
计算机硬件及网络远教产品技术交流的出现,为农村地区教育提供了现代化的解决方案,致力于缩小城乡教育差距。 早在1999年,中国教育电视台便启动了“现代远程教育卫星数字传输工程”,这一项目利用数字电视和多媒体...
计算机网络是由多台计算机通过通信设备相互连接,以实现数据传输、资源共享和信息交流的系统。这个定义涵盖了网络的两个关键要素:连接的计算机和通信机制。 在第一章中,作者谢希仁会追溯计算机网络的发展历程。从...
1. **支持远程通信**:使得不同地点的用户可以通过网络进行交流。 2. **支持多种服务**:如电子邮件、在线购物等,极大地丰富了人们的生活方式。 3. **提高工作效率**:对于企业和组织而言,有效的数据通信可以提高...
H3C网络工程师培训教材中的PPT对计算机网络的基础知识进行了详细的介绍,旨在帮助初学者建立起对网络的初步理解。 首先,计算机网络的定义是指由多个计算机和相关硬件设备,通过通信设备和介质互连,实现数据通信和...
2. 无站点网络营销:虽然企业没有自己的网站,但仍可通过电子邮件、邮件列表和新闻组等网络资源进行初步的营销活动。但这并不意味着这种营销方式属于高级网络营销,因为建立企业网站可以提供更全面的品牌展示和客户...
- 学校管理人员能够高效地处理各类管理事务,实现初步的办公自动化。 - **具体要求**: - 网络需要支持三层VLAN、端口隔离、链路聚合、STP、NAT等功能。 - 主服务器能够快速接入网络,确保充足的带宽和支持未来...