• 基于Socket实现网络编程


    Socket是网络上两个程序间双向通讯的一端,它既可以发送请求,也可以接收请求,利用它可以方便的编写网络上数据的传递,在java中,有专门的类类处理用户的请求和响应。利用Socket 类的方法,就可以实现两台计算机之间的通信,那么怎么利用socket进行网络编程呢?我试试水~

    网络中的进程之间是如何进行通信的?

    本地进程间通信(IPC)有很多种方法,简而言之可以归结为以下四类:

    1. 消息传递(管道,FIFO,消息队列);
    2. 同步(互斥量,条件变量,读写锁,文件和写记录锁,信号量);
    3. 内存共享(匿名的和具体的,线程等);
    4. 远程过程调用(Solaris门和Sun RPC)。

    那么,对于网络中的进程,如何实现通信呢?首先,我们要解决的是如何正确地唯一标识网络中的进程,在本地环境中,我们可以通过进程PID来进行标识,但是在网络中,不可以!但是网络中的IP地址却是唯一的可以标识一台计算机,而位于传输层的“网络+端口”可以唯一的标识主机中的应用程序(进程),这样,可以利用IP地址+协议+端口就可以标识网络中的进程啦!网络中的进程就可以利用这三元组和其他进程之间进行通信了!

    使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是为什么有人说“一切皆socket”。

    什么是Socket?

    socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。

    socket接口是TCP/IP网络协议的API,socket接口设计者最先将接口放在UNIX操作系统里面,如果了解UNix系统的输入和输出,Socket就很好理解了,网络中的数据传输是一种特殊的I/O, Socket也是一种文件描述符,也具有一个类似于打开文件的函数调用socket(),该函数返回一个整形的socket描述符,随后的连接建立,数据传输等操作都是通过该socket实现的。常用的socket类型有两种,流式Socket和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的Tcp服务应用,而数据报式socket是一种面向非连接的UDP服务应用。

    基于Socket的Java网络编程

    Socket所支持的协议不光TCP/IP一种,因此两者之间没有必然的联系,在Java中,socket编程主要是基于TCP/IP协议的网络编程。主要过程是:Server端Listen(监听)某个端口是否有连接请求,Client端向Server端发出Connect(连接)请求,Server端向Client端发回Accept消息,这样,一个连接就建立起来了,Server端和Client端都可以通过send,write等方法与对方进行通信。

    对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本步骤:

    1,创建Socket;

    2,打开连接到Socket的输入输出流;

    3,按照一定的协议对Socket进行读写操作;

    4,关闭socket。

    简单的例子:

    客户端程序:

    package com.leetch.socket;
    import java.awt.*;
    import java.io.*;
    import java.net.*;
    import java.io.StringReader;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    public class TestClient {
    	public static void main(String arg[]) throws Exception{
    		Socket tsocket = new Socket("127.0.0.1",4700);
    			
    		PrintWriter os = new PrintWriter(tsocket.getOutputStream());  
    		//由socket对象得到输出流,并构建PrintWriter对象
    		
    		BufferedReader bReader2 = new BufferedReader(
    				new InputStreamReader(tsocket.getInputStream()));
    		//由Socket对象得到输入流,并构造相应的BufferedReader对象
    		
    		Reader reader = StringReader(textArea.getText().toString());
    		BufferedReader bReader = new BufferedReader(reader);
    		//由textarea构造bufferedreader对象
    		
    		String readline = null;
    		readline = bReader.readLine();
    		
    		while(!readline.equals("bye")){  //结束判断标志
    			os.println(readline);  //把文本域里面的内容写到server端
    			os.flush();
    			System.out.println("Client:"+readline);
    			System.out.println("Server:"+bReader2.readLine());
    			readline = bReader.readLine();
    		}
    		os.close();
    		bReader2.close();
    		tsocket.close();
    	}
    
    	private static Reader StringReader(String string) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    服务器端代码:

    package com.leetch.socket;
    import java.io.*;
    import java.net.*;
    import java.applet.Applet;
    
    
    public class TServer{
    	public static void main(String args[]) {
    		try{
    			ServerSocket server=null;
    			server=new ServerSocket(4700);
    			System.out.println("正在监听端口...");  //创建一个ServerSocket在端口4700监听客户请求
    			
    			Socket socket=server.accept();   //创建一个socket,监听4700端口
    			
    			//由Socket对象得到输入流,并构造相应的BufferedReader对象
    			BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    			
    			//由Socket对象得到输出流,并构造PrintWriter对象
    			PrintWriter os=new PrintWriter(socket.getOutputStream());
    
    
    			//由系统标准输入设备构造BufferedReader对象
    			BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
    
    
    			System.out.println("Client:"+is.readLine());
    			//在标准输出上打印从客户端读入的字符串
    
    
    			String readline;
    			readline=sin.readLine();
    			
    			while(!readline.equals("quit")){   //终止条件
    				os.println(readline);   //向客户端返回请求值,及时刷新
    				os.flush();     
    				System.out.println("Server响应:"+readline);		//在系统标准输出上打印读入的字符串
    				System.out.println("Client请求:"+is.readLine());//读取client请求,并显示
    				readline=sin.readLine();  
    			}
    			System.out.println("已中断连接...");
    			os.close();
    			is.close(); 
    			socket.close();
    			server.close();
    		}catch(Exception e0){
    			e0.printStackTrace();
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    测试结果正确,客户端和服务器可以互通消息!

  • 相关阅读:
    Monorepo 解决方案 — 基于 Bazel 的 Xcode 性能优化实践
    [nlp] grad norm先降后升再降
    方差迭代公式推导
    Vue2源码学习笔记 - 16.响应式原理—更新调度
    为什么做的串口助手不能获取到虚拟串口,不知道是哪里出问题了,希望会的朋友解答一下,非常非常感谢
    swagger-01-swagger介绍
    php 将rsa私钥 从DER格式的私钥转换为 PEM 格式
    ATT&CK红队评估实战靶场二
    教大家电脑重装系统后如何设置硬盘密码
    Electron进程通信的另一种方式
  • 原文地址:https://blog.csdn.net/jiong9412/article/details/126565557