Java中的网络编程—Socket通信
来源:互联网 发布:淘宝字体侵权 编辑:程序博客网 时间:2024/05/18 18:20
一、网络基础知识
两台计算机要想通过网络进行通信,那么他们必须满足ip地址、协议、端口号这三个必然的条件
1、两台主机必须表明所在的身份和位置,也就是ip地址
2、必须有共同的语言,不然无法交流,也就是我们所说的协议
3、需要有相应的端口号,一台主机可以运行多个应用程序,怎么辨别不同通信的程序,那么就需要端口号来区分
TCP/IP协议
TCP/IP是目前世界上应用最为广泛的协议,是以TCP和IP为基础的不同层次上多个协议的集合,也称TCP/IP协议族或TCP/IP协议栈
TCP:Transmission Control Protocol 传输控制协议
IP:Internet Protocol 互联网协议
TCP/IP模型
一般来说,会将网络进行分层,常见的会把网络分为五层,叫TCP/IP模型
IP地址
为实现网络中不同计算机之间的通信,每台机器都必须有一个唯一的标识---IP地址
IP地址格式:数字型,如:192.168.0.1
IPv4:32位的二进制
端口
1、用于区分不同应用程序
2、端口号范围为0~65535,其中0~1023为系统所保留
3、IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链接的终结点,是TCP和UDP的基础
4、http:80 ftp:21 telnet:23
二、Java中网络相关API的应用
java中的网络支持
针对网络通信的不同层次,java提供的网络功能有四大类:
1、InetAddress:用于标识网络上的硬件资源
2、URL:统一资源定位符,通过url可以直接读写或写入网络上的数据
3、Socket:使用TCP协议实现网络通信的Socket相关的类
4、Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信
InetAddress类
1、InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址
2、实例如下
输入:
package rmd_intl_app.Test;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Arrays;/** * @Description: InetAddress类 */public class InetAddressTest {public static void main(String[] args) throws UnknownHostException {//获取本机InetAddress类的操作实例InetAddress address = InetAddress.getLocalHost();System.out.println("address计算机名:"+address.getHostName());System.out.println("addressIP地址:"+address.getHostAddress());byte[] bs = address.getAddress();//获取字节数组形式的ip地址System.out.println("字节数组的形式的IP:"+Arrays.toString(bs));System.out.println("直接输出InetAddress对象:"+address);//根据计算机名获取InetAddress实例InetAddress address2 = InetAddress.getByName("MS-20160808TVQL");System.out.println("address2获取计算机名:"+address2.getHostName());System.out.println("address2IP地址:"+address2.getHostAddress());//根据ip地址获取InetAddress实例InetAddress address3 = InetAddress.getByName("192.168.0.235");System.out.println("address3计算机名:"+address3.getHostName());System.out.println("address3IP地址:"+address3.getHostAddress());}}
输出:
address计算机名:MS-20160808TVQLaddressIP地址:192.168.0.235字节数组的形式的IP:[-64, -88, 0, -21]直接输出InetAddress对象:MS-20160808TVQL/192.168.0.235address2获取计算机名:MS-20160808TVQLaddress2IP地址:192.168.0.235address3计算机名:MS-20160808TVQLaddress3IP地址:192.168.0.235
URL
1、URL(Uniform Resoure Locator)统一资源定位符,表示Internet上某一资源的地址
2、URL由两部分组成,协议名称和资源名称,中间用冒号隔开
3、在java.net包中,提供了URL类来表示URL
4、实例如下
输入:
package rmd_intl_app.Test;import java.net.MalformedURLException;import java.net.URL;/** * @Description: url */public class Urltest {public static void main(String[] args) {try {//创建一个url实例URL url = new URL("https://www.taobao.com/");//?后面是参数,#后面是锚点URL u = new URL(url, "index.html?username=taobao#test");System.out.println("协议:"+u.getProtocol());System.out.println("主机:"+u.getHost());//如果没有指定端口号,则返回默认端口号,此时getPort()返回值为-1System.out.println("端口:"+u.getPort());System.out.println("文件路径:"+u.getPath());System.out.println("文件名称:"+u.getFile());System.out.println("相对路径:"+u.getRef());System.out.println("查询字符串:"+u.getQuery());} catch (MalformedURLException e) {e.printStackTrace();}}}输出:
协议:https主机:www.taobao.com端口:-1文件路径:/index.html文件名称:/index.html?username=taobao相对路径:test查询字符串:username=taobao
使用URL读取网页内容
1、通过urll对象的openStream()方法可以得到指定资源的输入流
2、通过输入流可以读取、访问网络上的数据
3、实例如下
输入:
package rmd_intl_app.Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.URL;/** * @Description: 使用URL读取网页内容 */public class UrlTest02 {public static void main(String[] args) {try {//创建url一个实例URL url = new URL("http://www.baidu.com");//通过url的openStream()方法获取url对象所表示的资源字节输入流InputStream is = url.openStream();//将字节输入流转换为字符输入流InputStreamReader isr = new InputStreamReader(is,"utf-8");//为字符输入流添加缓冲BufferedReader br = new BufferedReader(isr);//读取数据String data = br.readLine();//循环获取数据while(data != null){System.out.println(data);//输出数据data = br.readLine();}br.close();isr.close();is.close();} catch (IOException e) {e.printStackTrace();}}}
输出:
<!DOCTYPE html><!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
三、通过Socket实现TCP编程
Socket通信
TCP协议是面向连接,可靠的、有序的、以字节流的方式发送数据
基于TCP协议实现网络通信的类:客户端的Socket类和服务器端的ServerSocket类
Socket通信模型
三个步骤:建立连接(客户端和服务器端进行建立通信连接)、开始通信(客户端向服务器发送请求,服务器端响应请求,然后返回请求响应)、结束通信(关闭通信和连接请求)
Socket通信实现步骤
1、创建socket和ServerSocket
2、打开连接到Socket输入/输出流
3、按照协议对Socket进行读/写操作
4、关闭输入/输出流,关闭Socket
服务器端
1、创建ServerSocket对象,绑定监听端口
2、通过accept方法监听客户端请求
3、连接建立后,通过输入流读取客户端发送的请求信息
4、通过输出流向客户端发送响应信息
5、关闭相关资源
6、实例如下
package rmd_intl_app.Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;/** * @Description: 服务器端 */public class Server {public static void main(String[] args) {try {System.out.println("服务器端已经启动,等待连接...........");//1、创建ServerSocket服务器对象,指定绑定的端口并监听ServerSocket serverSocket = new ServerSocket(8080);Socket socket = serverSocket.accept();//进行监听,等待客户端连接//2、字节输入流InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is);//将字节流转换为字符流BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲String info = null;//3、循环读取客户端信息while ((info = br.readLine()) != null) {System.out.println("我是服务器,客户端说:"+info);}socket.shutdownInput();//关闭输入流//4、获取输出流,响应客户端请求OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);pw.write("我是服务器,非常欢迎你!");pw.flush();//5、关闭资源pw.close();os.close();br.close();isr.close();is.close();socket.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}
客户端
1、创建Socket对象,指明需要连接的服务器的地址和端口号
2、连接建立后,通过输出流向服务器端发送请求信息
3、通过输入流获取服务器响应的信息
4、关闭相关资源
5、实例如下
package rmd_intl_app.Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;/** * @Description: 客户端 */public class Client {public static void main(String[] args) {try {//1、创建socket客户端,指定服务器地址和端口Socket socket = new Socket("192.168.0.235",8080);//2、获取输出流,向服务器发送信息OutputStream os = socket.getOutputStream();//字节输出流PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流pw.write("hello word");pw.flush();//3、获取输入流,读取服务器端响应的信息InputStream is = socket.getInputStream();//字节输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));//为输入流添加缓冲String info = null;while ((info = br.readLine()) != null) {System.out.println("我是客户端,服务器端说:"+info);}socket.shutdownInput();//关闭输出流//4、关闭资源br.close();is.close();pw.close();os.close();socket.close();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
多线程下的通信
应用多线程来实现服务器与多客户端之间的通信
基本步骤:
1、服务器端创建ServerSocket,循环调用accept()等待客户端连接
2、客户端创建一个socket并请求和服务器端连接
3、服务器端接受客户端请求,创建socket与该客户端建立专线连接
4、建立两个连接的socket在一个单独的线程上对话
5、服务器端继续等待新的连接
实例如下:
1、服务器线程处理类
package rmd_intl_app.Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;/** * @Description: 服务器线程处理类 */public class ServerThread extends Thread{//和本线程相关的socketSocket socket = null;public ServerThread(Socket socket){this.socket = socket;}//线程执行的操作,响应客户端的请求public void run(){InputStream is = null;InputStreamReader isr = null;BufferedReader br = null;OutputStream os = null;PrintWriter pw = null;try {is = socket.getInputStream();//将字节流转换为字符流isr = new InputStreamReader(is);//为输入流添加缓冲br = new BufferedReader(isr);String info = null;//3、循环读取客户端信息while ((info = br.readLine()) != null) {System.out.println("我是服务器,客户端说:" + info);}socket.shutdownInput();//关闭输入流//获取输出流,响应客户端请求os = socket.getOutputStream();pw = new PrintWriter(os);pw.write("我是服务器,非常欢迎你!");pw.flush();} catch (Exception e) {e.printStackTrace();}finally{try {if(pw != null){pw.close();}if(pw != null){os.close();}if(pw != null){br.close();}if(pw != null){isr.close();}if(pw != null){is.close();}} catch (IOException e) {e.printStackTrace();}}}}
2、服务器端
package rmd_intl_app.Test;import java.io.IOException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;/** * @Description: 服务器端 */public class Server {public static void main(String[] args) {try {//创建ServerSocket服务器对象,指定绑定的端口并监听ServerSocket serverSocket = new ServerSocket(8080);System.out.println("服务端已经启动,等待客户端连接.....");Socket socket = null;//记录客户端的数量int count = 0;while(true){//进行监听,等待客户端连接socket = serverSocket.accept();//创建一个新线程ServerThread thread = new ServerThread(socket);//启动线程thread.run();count++;//统计客户端的数量System.out.println("客户端的数量为:"+count);InetAddress address = socket.getInetAddress();System.out.println("客户端IP为:"+address.getHostAddress());}} catch (IOException e) {e.printStackTrace();}}}
3、客户端
package rmd_intl_app.Test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;/** * @Description: 客户端 */public class Client {public static void main(String[] args) {try {//1、创建socket客户端,指定服务器地址和端口Socket socket = new Socket("192.168.0.235",8080);//2、获取输出流,向服务器发送信息OutputStream os = socket.getOutputStream();//字节输出流PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流pw.write("hello word");pw.flush();//3、获取输入流,读取服务器端响应的信息InputStream is = socket.getInputStream();//字节输入流BufferedReader br = new BufferedReader(new InputStreamReader(is));//为输入流添加缓冲String info = null;while ((info = br.readLine()) != null) {System.out.println("我是客户端,服务器端说:"+info);}socket.shutdownInput();//关闭输出流//4、关闭资源br.close();is.close();pw.close();os.close();socket.close();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
注意事项:
1、资源必须释放,关闭资源的代码可写的严谨点,且倒序以此关闭
2、服务器端优先启动
3、多线程下客户端可以多次启动,体验多线程效果
四、通过Socket实现UDP编程
UDP编程
UDP协议(用户数据报协议)是无连接、不可靠、无序的,相对来说传输速度比较快
UDP协议以数据报作为数据传输的载体。就是进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据所要达到的Socket(主机地址和端口号),然后在将数据报发送过去
操作相关类:
DatagramPacket:表示数据报包
DatagramSocket:进行端到端通信的类
UDP通信模型
服务器端实现步骤
1、创建DatagramSocket,指定端口号
2、创建DatagramPacket
3、接受客户端发送的数据信息
4、读取数据
5、实例如下
package rmd_intl_app.Test;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/** * @Description: 服务器端 */public class UDPServer {public static void main(String[] args) throws IOException {/** * 服务器端接受数据 *///1、创建服务器DatagramSocket,指定端口DatagramSocket socket = new DatagramSocket(8080);//2、创建数据报,用于接受客户端发送来的数据byte[] b = new byte[2014];//创建字节数组,指定接受数据包的大小DatagramPacket packet = new DatagramPacket(b, b.length);//3、接受客户端发送来的数据System.out.println("服务器已经启动,等待连接.....");socket.receive(packet);//此方法在接受数据之前会一直堵塞//4、读取数据String info = new String(b,0,packet.getLength());System.out.println("我是服务器,客户端说:"+info);/** * 服务器端响应数据 *///1、定义服务器的地址,端口号,数据InetAddress address = packet.getAddress();int port = packet.getPort();byte[] by = "欢迎您!".getBytes();//2、创建数据报,包含响应的数据信息DatagramPacket packet2 = new DatagramPacket(by, by.length, address, port);//3、响应客户端socket.send(packet2);//4、关闭资源socket.close();}}
客户端实现步骤
1、定义发送信息
2、创建DatagramPacket,包含将要发送的信息
3、创建DatagramSocket
4、实例如下
package rmd_intl_app.Test;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/** * @Description: 客户端 * @author lc * @date 2017年6月24日 */public class UDPClient {public static void main(String[] args) throws IOException {/** * 向服务器端发送数据 *///1、定义服务器的地址,端口号,数据InetAddress address = InetAddress.getByName("192.168.0.235");int port = 8080;byte[] data = "您好,我是客户端".getBytes();//2、创建数据报,包含发送的数据信息DatagramPacket packet = new DatagramPacket(data, data.length, address,port);//3、创建DatagramSocket对象DatagramSocket socket = new DatagramSocket();//4、向服务器端发送数据报socket.send(packet);/** * 接受服务器端响应的数据 *///1、创建数据报,用于接受服务器端响应的数据byte[] b = new byte[1024];DatagramPacket packet2 = new DatagramPacket(b,b.length);//2、接受服务器端响应的数据socket.receive(packet2);//3、读取数据String info = new String(b,0,packet2.getLength());System.out.println("我是客户端,服务器说:"+info);//4、关闭资源socket.close();}}
(以上是个人学习笔记,不对之处望指正)
- Java中的网络编程—Socket通信
- android中的网络通信(一) socket编程
- Java网络编程——Socket与ServerSocket阻塞通信
- java网络编程Socket通信常见异常
- java网络编程(6):socket通信
- Java网络编程之Socket通信
- java网络编程基础Socket通信应用
- Java通信之Socket网络编程
- Java网络通信之Socket编程
- 网络编程之Socket通信(Java)
- 网络通信 Socket 编程
- Java网络通信Socket
- java 网络通信 socket
- java中的网络支持-socket编程
- Java中的TCP/UDP网络通信编程
- Java中的TCP/UDP网络通信编程
- Java网络通信学习(一)- Java Socket 编程
- java socket 通信编程
- 变量的命名2
- fragment返回键处理
- unity委托的排序方法
- NYOJ 28 大数阶乘
- android内存泄漏解决方案
- Java中的网络编程—Socket通信
- 创建孟获的远古祭祀技能触发器
- 最小路径和
- ARRAY_SIZE
- thinking in java 阅读笔记 第六章 类再生
- React Native WebView组件实现的BarCode(条形码)、(QRCode)二维码
- 阅读ISE源码过程中重新对单例模式的理解
- Java开发中的23种设计模式详解----解释器模式(Interpreter)
- maven项目构建struts2框架项目遇到的org.apache.jasper.JasperException: Unable to compile class for JSP: