socket实现网络通信
1.1、网络通信的要素
通信双方的地址:
IP
端口号
例如:127.0.0.1:8080
网络通信的协议:
TCP/IP参考模型
总结:
网络编程中有两个问题
如何准确的定位到网络上的一台主机
找到主机之后如何进行通信
网络编程中的要素
IP和端口号(Port)
网络通信协议 UDP、TCP
1.2、IP
IP地址:InetAdress类
唯一定位一台网络上的计算机
127.0.0.1:本机IP(lochost)
IP地址分类
iPv4/ipv6
公网(互联网)-私网(局域网)
ADCD类地址
192.168.xxx.xxx组织内部专用
测试ip
import .InetAddress;import .UnknownHostException;//测试Ippublic class TextInetAdress {public static void main(String[] args) {try {//通过名字返回本机IPInetAddress inetAdress1 = InetAddress.getByName("127.0.0.1"); System.out.println(inetAdress1);//通过名字查询百度网IP地址InetAddress inetAdress2 = InetAddress.getByName("");System.out.println(inetAdress2);//通过名字返回本机IPInetAddress inetAdress3 = InetAddress.getByName("localhost"); System.out.println(inetAdress3);//通过名字返回本机IPInetAddress inetAdress4 = InetAddress.getLocalHost(); System.out.println(inetAdress4);//常用方法System.out.println(inetAdress2.getHostAddress());//规范的System.out.println(inetAdress2.getCanonicalHostName());System.out.println(inetAdress2.getHostName());} catch (UnknownHostException e) {e.printStackTrace();}}}
1.3、端口
端口表示计算机上的一个进程:
不同的进程有不同的端口号
TCP/UDP端口
单个协议下端口号不能冲突
端口分类:
共有端口 0-1023
HTTP : 80
HTTPS : 443
FTP : 21
Telent : 23
程序注册端口:-49151,分配给用户或者程序
Tomcat : 8080
MySQL : 3306
Oracle : 1521
import .InetSocketAddress;public class TextInetSocketAddress {public static void main(String[] args) {InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080);System.out.println(socketAddress1);InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);System.out.println(socketAddress2);}}
1.4、通信协议
TCP/IP协议簇
TCP:用户传输协议
UDP:用户数据报协议
TCP/UDP对比:
TCP
连接服务器
稳定
三次握手,四次挥手
客户端-服务器
传输完成,释放连接,效率低
UDP
不连接服务器
不稳定
无论另一端有无准备,都能发送
1.5、TCP
1.5.1、消息传输
客户端
连接服务器Socket
发送消息
import java.io.IOException;import java.io.OutputStream;import .InetAddress;import .Socket;//客户端public class TcpClientDemo1 {public static void main(String[] args) {Socket socket=null;OutputStream os=null;try {//要知道服务器的地址,端口号InetAddress serverIp = InetAddress.getByName("127.0.0.1");int port=9999;//创建一个socket链接socket = new Socket(serverIp,port);//发送消息I/O流os = socket.getOutputStream();os.write("你好,欢迎学习".getBytes());} catch (Exception e) {e.printStackTrace();}finally {if (os!=null)try {os.close();} catch (IOException e) {e.printStackTrace();}if (socket!=null)try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
服务器
建立服务的端口ServerSocket
等待用户的连接accept()
接受用户的消息
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import .ServerSocket;import .Socket;//服务器端public class TcpSeverDemo2 {public static void main(String[] args) {ServerSocket serverSocket=null;Socket accept=null;InputStream is=null;ByteArrayOutputStream baos=null;try {//我得有一个地址serverSocket = new ServerSocket(9999);//等待客户端连接过来while (true) {accept = serverSocket.accept();//读取客户端的内容is = accept.getInputStream();//管道流baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024]; //创建一个缓冲区int len; //用来判断是否将缓冲区的字节读完,读完则值为-1while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);//从buffer中写出数据到baos写出长度0-len}System.out.println(baos.toString());}} catch (Exception e) {e.printStackTrace();}finally {//关闭流资源if(baos!=null)try {baos.close();} catch (IOException e) {e.printStackTrace();}if (is!=null)try {is.close();} catch (IOException e) {e.printStackTrace();}if (accept!=null)try {accept.close();} catch (IOException e) {e.printStackTrace();}if (serverSocket!=null)try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}
1.5.2、文件传输
客户端
读取文件
创建连接
发送文件
import java.io.*;import .InetAddress;import .Socket;//读文件发送public class TcpFileDemo01 {public static void main(String[] args) throws Exception {//1创建一个socket连接获取端口和地址Socket socket=new Socket(InetAddress.getByName("127.0.0.1"),9000);//2获取一个输出流OutputStream os = socket.getOutputStream();//3读文件流FileInputStream fis = new FileInputStream(new File("zhushunsheng.jpg"));byte[] buffered=new byte[1024]; //自定义一个缓冲区int len; //用来判断是否将缓冲区的字节读完while ((len=fis.read(buffered))!=-1){os.write(buffered,0,len); //从buffer中写出数据到baos写出长度0-len}//通知服务器我已经结束了socket.shutdownOutput();//确认服务器接收完毕才能断开连接InputStream inputStream = socket.getInputStream();//String byte[]ByteArrayOutputStream baos=new ByteArrayOutputStream();byte[] buffer2=new byte[];int len2;while ((len2=inputStream.read(buffer2))!=-1){baos.write(buffer2,0,len2);}System.out.println(baos.toString());//4关闭资源baos.close();inputStream.close();fis.close();os.close();socket.close();}}
服务器
创建连接
监听连接
接收文件
import java.io.*;import .ServerSocket;import .Socket;//接收文件public class TcpFileDemo02 {public static void main(String[] args) throws Exception {//1创建服务ServerSocket serverSocket = new ServerSocket(9000);//监听客户端的连接Socket accept = serverSocket.accept();//2获取输入流InputStream is = accept.getInputStream();//3输出文件FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));byte[] buffer=new byte[1024];int len;while ((len=is.read(buffer))!=-1){fos.write(buffer,0,len);}//通知客户端我接收完毕了OutputStream os=accept.getOutputStream();os.write("我接收完毕了,你可以断开了".getBytes());//4关闭资源fos.close();is.close();accept.close();serverSocket.close();}}
注意事项:
如果文件在源文件目录下可以采用相对路径找到文件(这里采用此方式),如果文件不在源目录下则应采用绝对路径传输
1.6、UDP
模拟客户端1给客户端2发送消息
客户端1
创建连接
创建一个包
确认发送对象
发送包
import .DatagramPacket;import .DatagramSocket;import .InetAddress;//UDP不需要连接服务器public class UdpClientDemo1 {public static void main(String[] args) throws Exception {//建立一个socketDatagramSocket socket=new DatagramSocket(9999);//DatagramSocket数据报套接字//建立一个包String msg="你好";//发送给谁InetAddress lochost=InetAddress.getByName("127.0.0.1");int port=9090;//参数分别为数据,数据的长度,发送的地址,端口号DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, lochost, port);//发送包socket.send(packet);//关闭流socket.close();}}
客户端2
开放端口
接受数据
关闭连接
import .DatagramPacket;import .DatagramSocket;//还是要等待客户端的连接public class UdpSeverDemo2 {public static void main(String[] args) throws Exception {//开放端口DatagramSocket socket=new DatagramSocket(9090);//接收数据byte[] buffer= new byte[1024];DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收socket.receive(packet);//关闭连接socket.close();System.out.println(packet.getAddress().getHostAddress());System.out.println(new String(packet.getData(),0,packet.getLength()));}}
如果觉得《socket实现网络通信》对你有帮助,请点赞、收藏,并留下你的观点哦!