java网络编程之Socket编程
概念
网络编程分为BIO(传统IO)、NIO、AIO。Socket编程属于BIO这种传统IO。
InetAddress
java.net.InetAddress是JAVA中管理IP地址的类,常用
public static void main(String[] args) throws UnknownHostException {InetAdressDemo.getLocalHost();System.out.println("---------------------------");getHostByName("Lenovo-Autumn");}/*** 获取主机ip和主机名* @throws UnknownHostException*/public static void getLocalHost() throws UnknownHostException {//根据InetAddress获取主机名和主机ipInetAddress localHost = InetAddress.getLocalHost();System.out.println(localHost); //打印:Lenovo-Autumn/192.168.56.1//根据getLocalHost()返回的值获取ip和主机名String hostName = localHost.getHostName();String hostAddress = localHost.getHostAddress();System.out.println(hostName); //打印 Lenovo-AutumnSystem.out.println(hostAddress); //打印 192.168.56.1//根据切割获取主机名和ipString[] str = localHost.toString().split("/");System.out.println(str[0]); //打印 Lenovo-AutumnSystem.out.println(str[1]); //打印 192.168.56.1 }/*** 根据主机名称获取ip地址* @param otherName 主机名(可以是局域网中的机器名或者是域名或者是ip)* @throws UnknownHostException*/public static void getHostByName(String otherName) throws UnknownHostException {InetAddress otherHost = InetAddress.getByName(otherName);String hostName = otherHost.getHostName();String hostAddress = otherHost.getHostAddress();System.out.println(hostName); //打印 Lenovo-AutumnSystem.out.println(hostAddress); //打印 192.168.56.1System.out.println(otherHost); //打印:Lenovo-Autumn/192.168.56.1}
code
UDP
发送数据时必须指定接收端的IP地址和端口号,就好像发送货物的集装箱上面必须标明接收人的地址一样。
接收端不需要明确知道数据的来源,只需要接收到数据即可。
java.net.DatagramPackage
构造函数:
第一种是用来接受的数据包,不需要指定IP和端口,第二种是用来发送的数据包需要指定ip和端口
方法:
获取ip地址,获取服务器ip或者客户端ip
返回端口号,获取发送方或者
返回数据缓冲区
返回要发送或接受的数据包大小
java.net.DatagramSocket
DatagramPacket数据包的作用就如同是“集装箱”,可以将发送端或者接收端的数据封装起来。然而运输货物只有“集装箱”是不够的,还需要有码头。在程序中需要实现通信只有DatagramPacket数据包也同样不行,为此JDK中提供的一个DatagramSocket类。DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包,发送数据的过程如下图所示。
构造函数:
用来创建发送端的DatagramSocket对象
用来创建接收端的DatagramSocket对象
方法:
发送数据报包
接收数据报包
发送端
1, 创建DatagramSocket对象
DatagramSocket()
2,创建DatagramPacket对象,封装数据,并指定ip和端口。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
3,发送数据
socket.send(DatagramPacket dp)
4,释放流资源
ds.close();
接收端
1,创建DatagramSocket对象,只需要指定端口
DatagramSocket(port)
2,创建DatagramPacket对象
DatagramPacket(byte[] data, int length)
3,接收数据存储到DatagramPacket对象中
receive(DatagramPackage dp)
4,获取DatagramPacket对象的内容
new String(data,0,dp.getLength());
5,释放流资源
ds.close();
/*** 实现udp发送端* 用java.net.DatagramPackage封装数据* 用java.net.DatagramSocket发送数据** 实现步骤* 1.用DatagramPackage对象,封装数据,接受的地址和端口* 2.创建DatagramSocket* 3.调用DatagramSocket对象send方法,发送数据* 4.关闭资源** DatagramPackage构造函数* DatagramPacket(byte[] buf, int length, InetAddress address, int port)* DatagramSocket构造函数* DatagramSocket()* 方法:send(DatagramPacket d)* Created by Autumn on 2018/2/5.*/ public class UdpSend {public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);//获取地址InetAddress inet = InetAddress.getByName("127.0.0.1");//创建DatagramSocket,负责接受和发送数据DatagramSocket ds = new DatagramSocket();while(true){String msg = scanner.nextLine();//创建数据包对象对象byte[] data = msg.getBytes();//封装数据,接受的地址和端口DatagramPacket dp = new DatagramPacket(data,data.length,inet,6000);//发送数据包 ds.send(dp);if(msg.equals("exit")){break;}}//关闭 ds.close();} }/*** 实现udp接收端* 用java.net.DatagramPackage 接受数据* 用java.net.DatagramSocket 接受数据包** 步骤* 1.创建DatagramSocket对象,绑定端口号(要和发送端端口一致)* 2.创建字节数组用来接受数据* 3.创建数据对象包DatagramPackage* 4.创建DatagramSocket* receive(DatagramPackage dp)接受数据,将数据封装如dp中* 5.拆包* 发送端的ip地址(DatagramPackage.get)* 接受到的字节数组* 发送的端口号* 6.关闭资源* Created by Autumn on 2018/2/5.*/ public class UdpReceive {public static void main(String[] args) throws IOException {//创建数据包传输的对象,并绑定端口号DatagramSocket ds = new DatagramSocket(6000);//创建字节数组byte[] data = new byte[1024];while(true){//创建数据包对象,传递字节数组DatagramPacket dp = new DatagramPacket(data,data.length);//调用ds对象的receive接受数据包,receive()有线程阻塞效果会一直等待接受数据 ds.receive(dp);//获取数据包大小int len = dp.getLength();//获取发送端的ip地址InetAddress sendAddress = dp.getAddress();String sendHostAddress = sendAddress.getHostAddress();//System.out.println(sendHostAddress);//获取发送端端口号int port = dp.getPort();//System.out.println(port);//System.out.println(new String(data)); //直接打印1024个字节的字符串,有很多空格System.out.println(sendHostAddress+":"+port+" "+new String(data,0,len)); //这样打印没有多余的空格if(new String(data,0,len).equals("exit")){break;}}//关闭 ds.close();} }
code
TCP
ServerSocket类,用于表示服务器端,Socket类,用于表示客户端。建立连接后用流进行输入和输出
ServerSocket
实例化一个ServerSocket类,指定端口号
监听并接受此套接字的连接
返回此服务器套接字的本地地址
Socket
实例化一个Socket并指定ip和端口
返回一个输出流,用于客户端发送数据
返回一个输入流,用于服务器端接受数据
返回ip地址(服务器端的地址)
返回端口号
客户端
1,创建客户端的Socket对象,指定服务器IP和端口号
Socket(String host, int port)
2,获取Socket的输出流对象
getOutputStream();
3,写数据给服务器
out.write("服务器数据".getBytes());
4,关闭流资源
socket.close();
服务器端
1,创建服务器端ServerSocket对象,指定服务器端端口号
ServerSocket(int port)
2,开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
accept()
3,通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
socket.getInputStream();
4,通过客户端的输入流,获取流中的数据
byte[] data = new byte[1024];
int len = inputStream.read(data);
System.out.println(new String(data,0,len));
5,通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
6,通过客户端的输出流,写数据到流中
7,关闭流资源
socket.close();
serverSocket.close();
/*** 实现TCP服务器程序* 表示服务器程序的类java.net.ServerSocket* 构造方法:* ServerSocket(int port); 传递端口号** Important:必须获得客户端的套接字(Socket)* 方法:Socket accept()* 服务器可以获取到客户端的套接字* Created by Autumn on 2018/2/5.*/ public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8888);//调用服务器套接字对象accept()获取客户端套接字,具有线程等待效果Socket socket = serverSocket.accept(); //这里会阻塞等待连接接入 cmd中telnet 127.0.0.1 8888即可连接//根据获得的客户端的socket获取输入流InputStream inputStream = socket.getInputStream();//根据输入流将数据读入到data中byte[] data = new byte[1024];int len = inputStream.read(data); //这里会阻塞,等待数据 cmd中ctrl+]进入到telnet操作模式send value发送数据System.out.println(new String(data,0,len));socket.close();serverSocket.close();} }/*** 实现TCP客户端,连接到服务器* 和服务器实现数据交换* 实现TCP客户端程序的类 java.net.Socket** 构造方法:* Socket(String host, int port)传递服务器IP和端口号* 注意:构造方法只要运行,就会和服务器进行连接,连接时报,抛出异常** OutputStream getOutputStream() 返回套接字的输出流* 作用:将数据输出,输出到服务器* InputStream getInputStream() 返回套接字的输入流* 作用:从服务器端读取数据** 客户端服务器数据交换,必须使用套接字对象Socket中的获取的IO刘,自己new的流不行** Created by Autumn on 2018/2/5.*/ public class TCPClient {public static void main(String[] args) throws IOException {//创建Socket对象,连接服务器Socket socket = new Socket("127.0.0.1",8888);//通过客户端的套接字对象Socket方法,获取字节输出流,将数据写向服务器OutputStream out = socket.getOutputStream();out.write("这是一条来客户端的数据".getBytes());socket.close();} }
用cmd命令telnet实现和SocketServer互动
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;public class TCPServer {/*同步阻塞*/public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务端启动成功...");while(true){/*一次只能处理一个连接,在一个连接没关闭前无法接收第二个连接,在这里开一个框发送数无问题,开放两个框时会出现第二个无反应*/Socket socket = serverSocket.accept(); //这里会阻塞等待连接接入 cmd中telnet 127.0.0.1 8888即代表连接System.out.println("新客户端连接成功....");InputStream inputStream = socket.getInputStream();while(true) {byte[] data = new byte[1024];System.out.println("正在等待数据...");int len = inputStream.read(data); //这里会阻塞,等待数据,如果直接关闭cmd窗口会因为关闭socket通道导致len返回-1 cmd中ctrl+]进入到telnet操作模式send value发送数据if (len != -1){System.out.println(new String(data, 0,len, "GBK")); //用GBK是因为CMD窗口命令发送的数据是GBK编码}else{break;}}}//socket.close();//serverSocket.close();//System.out.println("服务器端关闭...."); } }
连接服务端
向服务端发送数据
再开一个cmd然后telnet发送数据,发现无反应。必须关闭第一个cmd才能连接成功。
线程池改进,能并发访问
用ExecutorService线程池实现每一个连接创建一个新的线程
import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class TCPServer {/*异步阻塞*/public static void main(String[] args) throws IOException {ExecutorService threadPool = Executors.newCachedThreadPool(); //线程池ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务端启动成功...");while(true){/*一次只能处理一个连接,在一个连接没关闭前无法接收第二个连接,在这里开一个框发送数无问题,开放两个框时会出现第二个无反应*/System.out.println("等待客户端连接...");final Socket socket = serverSocket.accept(); //这里会阻塞等待连接接入 cmd中telnet 127.0.0.1 8888即代表连接threadPool.execute(new Runnable() { //启动一个线程public void run() {try {System.out.println("新客户端连接成功....");InputStream inputStream = socket.getInputStream();while(true) {byte[] data = new byte[1024];System.out.println("正在等待数据...");int len = inputStream.read(data); //这里会阻塞,等待数据,如果直接关闭cmd窗口会因为关闭socket通道导致len返回-1 cmd中ctrl+]进入到telnet操作模式send value发送数据if (len != -1){System.out.println(Thread.currentThread()+new String(data, 0,len, "GBK")); //用GBK是因为CMD窗口命令发送的数据是GBK编码}else{System.out.println("break循环");break;}}System.out.println("一次Socket连接关闭");} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}});}//socket.close();//serverSocket.close();//System.out.println("服务器端关闭...."); } }
优点:传输质量好(所以BIO适合传输连接少但是数据量大的请求)
缺点:每一个连接都占用一个线程,很占用系统资源。
tip:所有的调优都关联到系统资源(IO、存储、内存、CPU)
code
转载于:https://www.cnblogs.com/aeolian/p/8417916.html
java网络编程之Socket编程相关推荐
- 浅谈Java网络编程之Socket (2)
<浅谈Java网络编程之Socket (1)>中我们已经和大家说到客户端的网络编程,下面和大家分享的是服务器的实现代码. import java.net.*; import java.io ...
- Java网络编程之NIO编程(待补充)
Java网络编程之NIO编程(待补充) 学习网站1:http://ifeve.com/java-nio-all/ 学习网站2:http://www.ibm.com/developerworks/cn/ ...
- 浅谈Java网络编程之Socket (1)
和大家一起分享的是Java网络编程之Socket.在Java中Socket可以理解为客户端或者服务器端的一个特殊的对象,这个对象有两个关键的方法,一个是getInputStream方法,另一个是get ...
- JAVA网络编程之Socket
Socket网络编成是一种较为底层的网络数据传输,很多语言都支持. 本例是根据菜鸟教程中的Java网络编程而写. 详细内容参考请参考:http://www.runoob.com/java/java-n ...
- 网络编程之 Socket 编程 一文看懂
但使龙城飞将在,只缘身在此山中 之前在 BIO.NIO 入门(Netty 先导) 一文中聊了 socket ,本文想把视野拉大,从计算机网络的纬度来聊聊 socket 温故而知新,聊聊网络模型 上图对 ...
- 网络编程之 socket编程
socket编程(基于linux下的网络编程) 提起网络编程那么我们就不得不说一下socket编程了(本博客主要是围绕下面这本书展开的). 感谢bingo大佬提供的书籍 链接: https://pan ...
- Python网络编程之socket编程
什么是Socket? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面 ...
- linux网络编程之socket编程(六)
经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:"真爱生活,珍惜生命",好了,言归正传. ...
- 超详细的逐句介绍Java网络编程之Socket类函数源码讲解(全)
一.Socket类 Socket 类表示通信双方中的客户端,用于呼叫远端机器上的一个端口,主动向服务器端发送数据(当连接建立后也能接收数据).下面我将从源码的角度来介绍Socket类的内部原理及其方法 ...
最新文章
- java中图片文件的判断
- uva 1416 (SPFA) **月赛第E题的原题**
- SpringBoot实用小技巧之动态设置SpringBoot日志级别
- rancher的微服务运维
- 10款微信公众平台相关的开源软件(转)
- Spring Data MongoDB级联保存在DBRef对象上
- python中字符串乘法_python leetcode 字符串相乘实例详解
- C++继承时名字的遮蔽
- 埃森哲:AI成新生产要素,2035年将中国经济增速提高1.6% | 附下载
- 使用SQL2005 递归查询结合Row_Number()实现完全SQL端树排序
- windows10下Qt安装及OpenCV配置
- 计算机指法标准,计算机键盘指法的正确练习步骤
- 神经内分泌肿瘤如何分级,神经系统分级调节概念
- tcl文件调用c语言,TCL与c/c++的互相调用
- 一、注册功能怎么测试
- 【教程】如果公司的网络屏蔽了游戏【英雄联盟】的链接请求,使用这种方法玩游戏。...
- html ppt播放音乐,PPT怎么控制音乐暂停后继续播放?
- 2023年国内十大SaaS软件公司排名
- WC .exe C语言实现
- 震惊!十六岁少女竟然被三名阿里p8老师讲解{常见面试题汇总}
热门文章
- crontab中执行postgresql命令
- 粒子滤波实现物体跟踪
- 在进行文字自绘时,自动换行打印
- PADS 9.5安装教程附安装包资源
- linux 并行执行脚本,在bash / linux中并行运行shell脚本
- 打开ADS提示23111@localhost后提示无法与执照伺服机连线,怎么解决?
- linux系统下用GCC、JAVA和Python编程
- 让数组的左边全为奇数C语言,2015年全国计算机等级考试全真模拟考场_二级C语言试卷四.docx...
- mysql索引组织结构_MySQL中创建及优化索引组织结构的思路(3)
- 小程序云服务器选什么系统好,小程序云服务器操作系统选择