十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
------- android培训、java培训、期待与您交流! ----------
成都创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计制作、成都做网站、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的仙游网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
概述
1、网络模型2,数据要发送到对方指定的应用程序上。为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。
为了方便称呼这个数据,叫做端口(逻辑端口);
3,定义通信规则。这个通讯规则称为协议。
国际组织定义了通用协议TCP/IP
端口范围:0~65535
0~1024一般都被系统预定的
常见端口:
web服务默认端口80
Tomcat默认端口8080
MySQL默认端口3306
--------------------------------------------------
数据模型
OSI数据模型 TCP/IP参考模型
----------------------------
应用层 |
-------------
表示层 | 应用层
-------------
会话层 |
----------------------------
传输层 | 传输层 TCP/UDP
----------------------------
网络层 | 网际层 IP地址协议
----------------------------
数据链路层 |
------------- 主机至网络层
物理层 |
----------------------------
-----------------------------------------------------------
IP地址static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。
----------------------------------------------------------
UDP和TCP
UDP
1、面向无连接。
2、将数据及源和目的封装成数据包中,不需要建立连接。每个数据包的大小限制在64K内。
3,因为无连接,是不可靠协议。
4,不需要建立连接,速度快。
例子:聊天软件。视频会议。只追求速度,即便丢失部分数据无伤大雅。
TCP
建立连接,形成传输数据的通道。
在连接中进行大数据量传输。
通过三次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
--------------------------------------------------------------------------
Socket服务
1、Socket就是为网络服务提供的一种机制
2、通信的两端都有Socket
3、网络通信其实就是Soket间的通信
4、数据在两个Socket间通过IO传输
---------------------------------------------------------------------------------------------------
UDP发送端和接收端
import java.net.*; /* 需求:通过udp传输方式,将一段文字数据发送出去。 定义一个udp发送端。 思路: 1,建立udpsocket服务。 2,提供数据,并将数据封装到数据包中。 3,通过socket服务的发送功能,将数据包发送出去。 4,关闭资源。 */ class UdpSend { public static void main(String[] args) throws Exception { //1,创建udp服务,通过DatagramScket对象。 DatagramSocket ds = new DatagramSocket(); //2。确定数据,并封装成数据包。 byte[] data = "udp ge men lai le".getBytes(); DatagramPacket dp = //数据包数组 //长度 //目的地址。 //目的端口号 new DatagramPacket(data,data.length,InetAddress.getByName("10.182.177.226"),1000); //3,通过socket服务,将已有的数据包发送出去,通过send方法。 ds.send(dp); //关闭资源。 ds.close(); } } /* 需求: 定义一个应用程序,用于接收udp协议传输的数据并处理。 定义udp的接收端。 思路: 1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接受网络应用程序定义数字标识。 方便于明确哪些数据过来改应用程序可以处理。 2,定义一个数据包(没有数据),因为要存储接受到的字节数据,因为数据包对象中有更多功能可以提前字节数据中的不同数据信息。 3,通过socket服务的receive方法将接受到的数据存入定义好的数据包中。 4,通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。 5,关闭资源。 */ class UdpRece { public static void main(String[] args) throws Exception { //1,创建udp socket,建立端点。 DatagramSocket ds = new DatagramSocket(10000); while(true) { //2,定义数据包,用于存储数据。 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); //3,通过服务的receive方法将接受到的数据存入数据包中。 ds.receive(dp); //4,通过数据包的方法获取其中的数据。 String ip = dp,getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); int port = dp.getPort(); System.out.println(ip+":"+data+";"+port); } //关闭资源。 //ds.close(); } }
---------------------------------------------------------------------------
UDP-使用键盘录入方式传输数据。
import java.net.*; import java.io.*; class UdpSend2 { public static void main(String[] args) throws Exception { //创建UDP服务。 DatagramSocket ds = new DatagramSocket(); //键盘录入。 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line = bufr.readLine())!=null) { if("over" .equals(line))//判断结束标记 break; byte[] buf = line.getBytes(); //定义用于发送的数据报包,将数据发送端指定的主机的端口上。 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10001); ds.send(dp); } ds.close(); } } class UdpRece2 { public static void main(String[] args)throws Exception { //创建udp服务,并指定端口。 DatagramSocket ds = new DatagramSocket(10001); while (true) { byte[] buf = new byte[1024];//定义容器,存储数据。 //定义用于接收的数据报包。 DatagramPacket dp = new DatagramPacket(buf,buf.length); //接受数据报包。 ds.receive(dp); String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+":"+data); } } }
--------------------------------------------------------------------------
UDP-聊天程序
/* 编写一个聊天程序。 有收数据的部分,和发数据的部分。 这两部分需要同时执行。 那就需要用到多线程技术。 一个线程控制收,一个线程控制发。 因为收和发动作是不一致的,所以要定义两个run方法。 而且这两个方法要封装到不同的类中。 */ import java.net.*; import java.io.*; class Send implements Runnable { private DatagramSocket ds; public Send(DatagramSocket ds) { this.ds = ds; } public void run() { try { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line = bufr.readLine())!=null) { if("over".equals(line)) break; byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10002); ds.send(dp); } } catch (Exception e) { throw new RuntimeException("发送失败"); } } } class Rece implements Runnable { private DatagramSocket ds; public Rece(DatagramSocket ds) { this.ds = ds; } public void run() { try { while (true) { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf,buf.length); ds.receive(dp); String ip = dp.getAddress().getHostAddress(); String data = new String(dp.getData(),0,dp.getLength()); System.out.println(ip+":"+data); } } catch (Exception e) { throw new RuntimeException("接受失败"); } } } class ChatDemo { public static void main(String[] args) throws Exception { DatagramSocket sendSocket = new DatagramSocket(); DatagramSocket receSocket = new DatagramSocket(10002); new Thread(new Send(sendSocket)).start(); new Thread(new Rece(receSocket)).start(); } }
---------------------------------------------------------
TCP-服务端和客户端
/* 演示tcp传输。 1,tcp分客户端和服务端。 2,客户端对应的对象时Socket。 服务端对应的对象时ServerSocket。 */ /* 客户端 通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。 因为tcp是面向连接的。所以在建立socket服务时, 就要有服务端操作,并连接成功。形成通路后,在该通道进行数据的传输。 需求:给服务端发生一个文本数据。 步骤: 1,创建socket访问,并指定要连接的主机和端口。 */ import java.io.*; import java.net.*; class TcpClient { public static void main(String[] args) throws Exception { //创建客户端的socket服务,指定目的主机和端口。 Socket s = new Socket("127.0.0.1",10003); //为了发送数据,应该获取socket流中的输入流。 OutputStream os = s.getOutputStream(); os.write("tcp ge men lai le".getBytes()); s.close(); } } /* 需求:定义端点接受数据并打印在控制台上。 服务端: 1,建立服务端的socket服务,SeverSocket(); 并监听一个端口。 2,获取连接过来的客户端对象。 通过ServerSocket的accept方法。没有连接就会等,所以这个方法时阻塞式的。 3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。 并打印在控制台。 4,关闭服务器.(可选) */ class TcpServer { public static void main(String[] args) throws Exception { //建立服务端socket服务,并监听一个端口。 ServerSocket ss = new ServerSocket(10003); //通过accept方法获取连接过来的客户端对象。 Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"---connected"); //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); ss.close(); } }
------------------------------------------------------------------------------
TCP--客户端与服务端的互访
import java.io.*; import java.net.*; /* 演示tcp的传输的客户端和服务端的互访。 需求:客户端给服务端发生数据,服务端收到后,给刚看的反馈信息。 */ /* 客户端: 1,建立socket服务。指定要连接主机和端口。 2,获取socket流中的输出流,将数据写到该流中。通过网络发送给服务端。 3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。 4,关闭客户端资源。 */ class TcpClient2 { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10004); OutputStream out = s.getOutputStream(); out.write("服务端,你好".getBytes()); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close(); } } class TcpServer2 { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10004); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"---connect"); InputStream in =s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); OutputStream out = s.getOutputStream(); out.write("收到,哥们你也好".getBytes()); s.close(); ss.close(); } }
-----------------------------------------------------------------
TCP练习——实现服务端的文本转换
/* 需求:建立一个文本转换服务器。 客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。 而且客户端可以不断的进行文本转换。当客户端输入over时,转换结束。 分析: 客户端: 既然是操作设备上的数据,就可以使用io技术,并按照io的操作规律来思考。 源:键盘录入。 目的:网络设备,网络输出流。而且操作的文本数据。可以选择字符流。 步骤: 1,建立服务。 2,获取键盘录入。 3,将数据发送给服务端。 4,获取服务端返回的大写数据。 5,结束。关闭资源。 */ import java.io.*; import java.net.*; class TransClient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10005); //定义读取键盘数据的流对象。 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //定义目的,将数据写入到socket输入流,发给服务端。 //BufferedWriter bufOut = //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); //定义一个socket读取流,读取服务端返回的大写信息。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while ((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line); //bufOut.write(line); //bufOut.newLine(); //bufOut.flush(); String str = bufIn.readLine(); System.out.println("server:"+str); } bufr.close(); s.close(); } } /* 服务端: 获取socket对象。 源:socket读取流。 目的:serversocket输出流。 */ class TransServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10005); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"-----connected"); //读取socket读取流中的数据。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); //目的。socket输出流。将大写数据写入到socket输出流,并发生个客户端。 //BufferedWriter bufOut = //new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=bufIn.readLine())!=null) { System.out.println(line); out.println(line.toUpperCase()); //bufOut.write(line.toUpperCase()); //bufOut.newLine(); //bufOut.flush(); } s.close(); ss.close(); } } /* 该例子出现的问题。 出现:客户端和服务端都在莫名等等等。 为什么呢? 因为客户端和fws都有阻塞式的方法。这些方法没有读到结束标记。那么就一直等。 而导致两端,都在等待。 */
----------------------------------------------------------------------------
TCP——上传文本
import java.io.*; import java.net.*; class TextClient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10006); BufferedReader bufr = new BufferedReader(new FileReader("IpDemo.java")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; while ((line=bufr.readLine())!=null) { out.println(line); } s.shotdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bufIn.readLine(); System.out.println(str); bufr.close(); s.close(); } } class TextServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true); String line = null; while((line=bufIn.readLine())!=null) { out.println(line); } PrintWriter pw = new PrintWriter(s.getOutputStream(),true); pw.println("上传成功"); } }
------------------------------------------------------
TCP--多客户端并发上传图片
/* 需求:上传图片。 */ /* 客户端 1,服务端点。 2,读取客户端已有的数据。 3,通过socket输出流发给服务端。 4,读取服务端反馈信息。 5,关闭。 */ import java.net.*; import java.io.*; class PicClient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10007); FileInputStream fis = new FileInputStream(file); OutputStream out = s.getOutputStream(); byte[] buf = new byte[1024]; int len =0; while ((len=fis.read(buf))!=-1) { out.write(buf,0,len); } s.shutdownOutput(); InputStream in = s.getInputStream(); byte[] bufIn = new byte[1024]; int num = in.read(bufIn); System.out.println(new String(bufIn,0,num)); fis.close(); s.close(); } } /* 服务端 这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程。 这时B客户端连接,只有等待。 因为服务端还没有处理完A客户端的请求,还没有循环回来执行下次accpet方法。 所以,暂时获取不到B客户端对象。 为了可以让多个客户端同时并发访问服务端。 那么服务端最好就是将没有客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。 如何定义线程呢? 只有明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。 */ class PicThread implements Runnable { private Socket s; PicThread(Socket s) { this.s = s; } public void run() { int count =1; String ip = s.getInetAddress().getHostAddress(); try { System.out.println(ip+"----connect"); InputStream in = s.getInputStream(); File file = new File(ip+"("+(count)+").jpg"); while (file.exists()) { file = new File(ip+"("+(count++)+").jpg"); } FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[1024]; int len = 0; while ((len=in.read(buf))!=-1) { fos.write(buf,0,len); } OutputStream out = s.getOutputStream(); out.write("上传成功".getBytes()); fos.close(); s.close(); } catch (Exception e) { throw new RuntimeException(ip+"上传失败"); } } } class PicServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10007); while (true) { Socket s = ss.accept(); new Thread(new PicThread(s)).start(); } //ss.close(); } }
-------------------------------------------------------------
TCP——模拟用户登陆
/* 客户端通过键盘录入用户名。 服务端对这个用户名进行校验。 如果该用户存在,在服务端显示xxx,已登录。 并在客户端显示 xxx,欢迎光临。 如果该用处不存在,在服务端显示xxx,尝试登陆。 并在客户端显示 xxx,该用户不存在。 最多就登陆三次。 */ import java.net.*; import java.io.*; class LoginClient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1",10008); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(s.getOutputStream(),true); BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); for (int x=0;x<3 ;x++ ) { String line = bufr.readLine(); if(line==null) break; out.println(line); String info = bufIn.readLine(); System.out.println("info:"+info); if(info.contains("欢迎")) break; } bufr.close(); s.close(); } } class UserThread implements Runnable { private Socket s; UserThread(Socket s) { this.s = s; } public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"----------connected"); try { for(int x =0;x<3;x++) { BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String name = bufIn.readLine(); if(name==null) break; BufferedReader bufr = new BufferedReader(new FileReader("user.txt")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null; boolean flag = false; while ((line=bufr.readLine())!=null) { if (line.equals(name)) { flag =true; break; } } if (flag) { System.out.println(name+",已登录"); out.println(name+",欢迎光临"); break; } else { System.out.println(name+",尝试登陆"); out.println(name+",用户名不存在"); } } s.close(); } catch (Exception e) { throw new RuntimeException(ip+"校验失败"); } } } class LoginServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10008); while (true) { Socket s = ss.accept(); new Thread(new UserThread(s)).start(); } } }
-------------------------------------------------------------------------
自定义客户端(服务端—Tomcat;客户端-浏览器)
/* 演示客户端和服务端。 1,客户端:浏览器 服务端:自定义 2,客户端:浏览器 服务端:Tomcat服务器。 */ import java.net.*; import java.io.*; class ServerDemo { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(11000); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"----connected"); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String (buf,0,len)); PrintWriter out = new PrintWriter(s.getOutputStream(),true); out.println("客户端你好"); s.close(); ss.close(); } }
自定义图形化界面浏览器
import java.awt.*; import java.awt.event.*; import java.io.*; class MyIEByGUI { private Frame f; private Button but; private TextField tf; private TextArea ta; private Dialog d;//什么时候出错什么时候创建对象。放在这里只是便于阅读。 private Label lab; private Button okBut; MyIEByGUI() { init(); } public void init() { f = new Frame("My Window"); f.setBounds(300,100,500,400); f.setLayout(new FlowLayout()); d = new Dialog(f,"提示信息-self",true);//模式为true时,后面的窗体不能操作。 d.setBounds(400,200,240,150); d.setLayout(new FlowLayout()); lab = new Label(); okBut = new Button("确定"); d.add(lab); d.add(okBut); tf = new TextField(40); but = new Button("转到"); ta = new TextArea(20,60);//20行,60列 f.add(tf);//注意,因为流式布局,所以按顺序添加。 f.add(but); f.add(ta); myEvent(); f.setVisible(true); } private void myEvent() { d.addWindowListener(new WindowAdapter() { public void windowCloing(WindowEvent e) { d.setVisible(false);//不需要关闭。 } }); okBut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(false); } }); tf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_ENTER) showDir(); } }); but.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showDir(); } }); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } private void showDir() { String url = tf.getText(); int index1 = url.indexof("//")+2; int index2 = url.indexof("/",index1); String str = url.substring(index1,index2); String path = url.substring(index2); ta.setText(); } public static void main(String[] args) { new MyIEByGUI(); } }
--------------------------------------------------------------------
URL
1.创建URL类
URL类的构造方法主要有如下几种
URL(String spec):使用指定的字符串构建。
URL(String protocol, String host, int port, String file):使用指定的协议、主机名、端口号、文件名创建。
URL(String protocol, String host, String file):使用指定的协议、主机名、文件名创建。
URL(URL context, String spec):使用基地址和相对URL创建。
import java.net.*; import java.io.*; class URLConnectionDemo { public static void main(String[] args) throws Exception { URL url = new URL("http://127.0.0.1:8080/myweb/demo.html?name=lisi&age=30"); URLConnection conn = url.openConnection(); System.out.println(conn); InputStream in =conn.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); } }
2、常用方法
String getFile()
获取此 URL 的文件名。
String getHost()
获取此 URL 的主机名(如果适用)。
String getPath()
获取此 URL 的路径部分。
int getPort()
获取此 URL 的端口号。
String getProtocol()
获取此 URL 的协议名称。
String getQuery()
获取此 URL 的查询部分
import java.net.*; class URLDemo { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://127.0.0.1:8080/myweb/demo.html?name=lisi&age=30"); System.out.println("getProtocol() :"+url.getProtocol() );//获取协议 System.out.println("getHost() :"+url.getHost() );//获取主机信息 System.out.println("getPort() :"+url.getPort() );//获取端口信息。 System.out.println("getPath() :"+url.getPath() );//路径 System.out.println("getFile() :"+url.getFile() );//文件 System.out.println("getQuery() :"+url.getQuery() );//获取此 URL 的查询部分,即name=lisi&age=30 } }