Socket:Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。

Socket API 分类:

1.UDP数据报套接字编程:

DatagramSocket 构造方法:

方法签名 方法说明
DatagramSocket() 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口
(一般用于客户端)
DatagramSocket(int
port)
创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用
于服务端)

DatagramSocket 方法:

方法签名 方法说明
void
receive(DatagramPacket p)
从此套接字接收数据报(如果没有接收到数据报,该方法会阻
塞等待)
void send(DatagramPacket
p)
从此套接字发送数据报包(不会阻塞等待,直接发送)
void close() 关闭此数据报套接字

DatagramPacket 构造方法:

方法签名 方法说明
DatagramPacket(byte[]
buf, int length)
构造一个DatagramPacket以用来接收数据报,接收的数据保存在
字节数组(第一个参数buf)中,接收指定长度(第二个参数
length)
DatagramPacket(byte[]
buf, int offset, int length,
SocketAddress address)
构造一个DatagramPacket以用来发送数据报,发送的数据为字节
数组(第一个参数buf)中,从0到指定长度(第二个参数
length)。address指定目的主机的IP和端口号

DatagramPacket 方法:

方法签名 方法说明
InetAddress
getAddress()
从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取
接收端主机IP地址
int getPort() 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获
取接收端主机端口号
byte[] getData() 获取数据报中的数据

构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用InetSocketAddress 来创建。

InetSocketAddress API
InetSocketAddress ( SocketAddress 的子类 )构造方法:

方法签名 方法说明
InetSocketAddress(InetAddress addr, int port) 创建一个Socket地址,包含IP地址和端口号

示例一:实现一个回显服务(EchoServer)=》一发一收(发什么就返回什么)

UDP服务端代码实现:

package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;// 站在服务器的角度:
// 1. 源 IP: 服务器程序本机的 IP
// 2. 源端口: 服务器绑定的端口 (此处手动指定了 9090)
// 3. 目的 IP: 包含在收到的数据报中. (客户端的IP)
// 4. 目的端口: 包含在收到的数据报中. (客户端的端口)
// 5. 协议类型: UDP
public class UdpEchoServer {// 进行网络编程, 第一步就需要先准备好 socket 实例~ 这是进行网络编程的大前提.private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}// 启动服务器.public void start() throws IOException {System.out.println("启动服务器!");// UDP 不需要建立连接, 直接接收从客户端来的数据即可while (true) {// 1. 读取客户端发来的请求DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);socket.receive(requestPacket); // 为了接受数据, 需要先准备好一个空的 DatagramPacket 对象, 由 receive 来进行填充数据// 把 DatagramPacket 解析成一个 StringString request = new String(requestPacket.getData(), 0, requestPacket.getLength(), "UTF-8");// 2. 根据请求计算响应(由于咱们这是一个回显服务, 2 省略)String response = process(request);// 3. 把响应写回到客户端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf("[%s:%d] req: %s, resp: %s\n",requestPacket.getAddress().toString(), requestPacket.getPort(), request, response);}}// 由于是回显服务, 响应就和请求一样了.// 实际上对于一个真实的服务器来说, 这个过程是最复杂的. 为了实现这个过程, 可能需要几万行, 几十万行代码....public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}

代码解析:

UDP客户端代码实现:

package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP;private int serverPort;// 站在客户端的角度:// 源 IP: 本机 IP// 源端口: 系统分配的端口// 目的 IP: 服务器的 IP// 目的端口: 服务器的端口// 协议类型: UDPpublic UdpEchoClient(String ip, int port) throws SocketException {// 此处的 port 是服务器的端口.// 客户端启动的时候, 不需要给 socket 指定端口. 客户端自己的端口是系统随机分配的~~socket = new DatagramSocket();serverIP = ip;serverPort = port;}public void start() throws IOException {Scanner scanner = new Scanner(System.in);while (true) {// 1. 先从控制台读取用户输入的字符串System.out.print("-> ");String request = scanner.next();// 2. 把这个用户输入的内容, 构造成一个 UDP 请求, 并发送.//    构造的请求里包含两部分信息://    1) 数据的内容. request 字符串//    2) 数据要发给谁~ 服务器的 IP + 端口DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(serverIP), serverPort);socket.send(requestPacket);// 3. 从服务器读取响应数据, 并解析DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);socket.receive(responsePacket);String response = new String(responsePacket.getData(), 0, responsePacket.getLength(), "UTF-8");// 4. 把响应结果显示到控制台上.System.out.printf("req: %s, resp: %s\n", request, response);}}public static void main(String[] args) throws IOException {// 由于服务器和客户端在同一个机器上, 使用的 IP 仍然是 127.0.0.1 . 如果是在不同的机器上, 当然就需要更改这里的 IP 了UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
}

代码解析:

示例二:写一个简单的翻译程序(使用UDP协议)

UDP服务器代码:

package network;import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;public class UdpDictServer extends UdpEchoServer {private HashMap<String, String> dict = new HashMap<>();public UdpDictServer(int port) throws SocketException {super(port);// 简单构造几个词dict.put("cat", "小猫");dict.put("dog", "小狗");dict.put("fuck", "卧槽");dict.put("pig", "小猪");}@Overridepublic String process(String request) {return dict.getOrDefault(request, "该词无法被翻译!");}public static void main(String[] args) throws IOException {UdpDictServer server = new UdpDictServer(9090);server.start();}
}

注意:如果想要启动多个客户端,可以设置一下IDEA

2.TCP流套接字编程:

  • ServerSocket API
  • Socket API

ServerSocket API: ServerSocket 是创建TCP服务端Socket的API

ServerSocket 构造方法:

方法签名 方法说明
ServerSocket(int port) 创建一个服务端流套接字Socket,并绑定到指定端口

ServerSocket 方法:

方法签
方法说明
Socket
accept()
开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket
对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void
close()
关闭此套接字

Socket API: Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

方法签名 方法说明
Socket(String host, int
port)
创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的
进程建立连接

Socket 方法:

方法签名 方法说明
InetAddress getInetAddress() 返回套接字所连接的地址
InputStream getInputStream() 返回此套接字的输入流
OutputStream getOutputStream() 返回此套接字的输出流

示例一:写一个回显服务(使用TCP)

TCP服务端代码:

package network;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoServer {// listen => 英文原意 监听~~// 但是在 Java socket 中是体现不出来 "监听" 的含义的~~// 之所以这么叫, 其实是 操作系统原生的 API 里有一个操作叫做 listen// private ServerSocket listenSocket = null;private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while (true) {// 由于 TCP 是有连接的, 不能一上来就读数据, 而要先建立连接. (接电话)// accept 就是在 "接电话", 接电话的前提是, 有人给你打了~~, 如果当前没有客户端尝试建立连接, 此处的 accept 就会阻塞.// accept 返回了 一个 socket 对象, 称为 clientSocket. 后续和客户端之间的沟通, 都是通过 clientSocket 来完成的.// 进一步讲, serverSocket 就干了一件事, 接电话~~Socket clientSocket = serverSocket.accept();processConnection(clientSocket);}}private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端建立连接!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());// 接下来来处理请求和响应// 这里的针对 TCP socket 的读写就和文件读写是一模一样的!!try (InputStream inputStream = clientSocket.getInputStream()) {try (OutputStream outputStream = clientSocket.getOutputStream()) {// 循环的处理每个请求, 分别返回响应Scanner scanner = new Scanner(inputStream);while (true) {// 1. 读取请求if (!scanner.hasNext()) {System.out.printf("[%s:%d] 客户端断开连接!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());break;}// 此处用 Scanner 更方便. 如果不用 Scanner 就用原生的 InputStream 的 read 也是可以的String request = scanner.next();// 2. 根据请求, 计算响应String response = process(request);// 3. 把这个响应返回给客户端// 为了方便起见, 可以使用 PrintWriter 把 OutputStream 包裹一下PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);// 刷新缓冲区, 如果没有这个刷新, 可能客户端就不能第一时间看到响应结果.printWriter.flush();System.out.printf("[%s:%d] req: %s, resp: %s\n", clientSocket.getInetAddress().toString(),clientSocket.getPort(), request, response);}}} catch (IOException e) {e.printStackTrace();} finally {// 此处要记得来个关闭操作.try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

代码解析:

TCP客户端代码:

package network;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {// 用普通的 socket 即可, 不用 ServerSocket 了// 此处也不用手动给客户端指定端口号, 让系统自由分配.private Socket socket = null;public TcpEchoClient(String serverIP, int serverPort) throws IOException {// 其实这里是可以给的. 但是这里给了之后, 含义是不同的. ~~// 这里传入的 ip 和 端口号 的含义表示的不是自己绑定, 而是表示和这个 ip 端口建立连接!!// 调用这个构造方法, 就会和服务器建立连接 (打电话拨号了)socket = new Socket(serverIP, serverPort);}public void start() {System.out.println("和服务器连接成功!");Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream()) {try (OutputStream outputStream = socket.getOutputStream()) {while (true) {// 要做的事情, 仍然是四个步骤// 1. 从控制台读取字符串System.out.print("-> ");String request = scanner.next();// 2. 根据读取的字符串, 构造请求, 把请求发给服务器PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);printWriter.flush(); // 如果不刷新, 可能服务器无法及时看到数据.// 3. 从服务器读取响应, 并解析Scanner respScanner = new Scanner(inputStream);String response = respScanner.next();// 4. 把结果显示到控制台上.System.out.printf("req: %s, resp: %s\n", request, response);}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}
}

代码解析:

 问题:

方法一:使用多线程

方法二:使用线程池:

示例二:完成一个简单的翻译程序(使用TCP)

同样的也只需要修改TCP服务端即可

TCP服务端代码:

package network;import java.io.IOException;
import java.util.HashMap;public class TcpDictServer extends TcpThreadPoolEchoServer {private HashMap<String, String> dict = new HashMap<>();public TcpDictServer(int port) throws IOException {super(port);dict.put("cat", "小猫");dict.put("dog", "小狗");dict.put("pig", "小猪");dict.put("fuck", "卧槽");}@Overridepublic String process(String request) {return dict.getOrDefault(request, "当前的词无法翻译");}public static void main(String[] args) throws IOException {TcpDictServer server = new TcpDictServer(9090);server.start();}
}

代码解析:

网络编程套接字(Socket编程)相关推荐

  1. Java套接字Socket编程--TCP参数

    在Java的Socket中,主要包含了以下可设置的TCP参数. 属性 说明 默认值 SO_TIMEOUT 对ServerSocket来说表示等待连接的最长空等待时间; 对Socket来说表示读数据最长 ...

  2. 网络编程套接字Socket

    首先理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址 了解端口号 端口号(port)是传输层协议的内容 端口号是一个32位的整数 端口号用来标 ...

  3. 套接字Socket编程

    Socket,原意插座.插口.写软件程序时,可以想象成一根网线,一头插在客户端,一头插在服务端,然后进行通信.所以通信前,双方都要建立一个Socket. Socket编程进行的是端到端的通信,意识不到 ...

  4. 网络 IPC 套接字socket

    APUE书中所有实例源码下载地址:http://www.apuebook.com apue学习笔记(第十六章 网络IPC:套接字):https://www.cnblogs.com/runnyu/p/4 ...

  5. Linux - 第12节 - 网络编程套接字(一)

    目录 1.预备知识 1.1.理解源IP地址和目的IP地址 1.2.理解源MAC地址和目的MAC地址 1.3.理解源端口号和目的端口号 1.4.理解端口号(PROT)和进程ID(PID) 1.5.认识T ...

  6. [python学习] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

    很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识   ...

  7. socket网络编程套接字TCP/UDP两种方式详解

    目录 准备知识 源IP地址和目的IP地址 端口号与进程ID 传输层协议--TCP 传输层协议--UCP 网络字节序 socket套接字介绍 概念 常见的三种socket socket编程常见API s ...

  8. 网络编程:套接字socket函数与绑定信息bind函数

    套接字socket函数与绑定信息bind函数 套接字 绑定信息(绑定IP和端口) socket函数 bind函数 struct sockaddr结构体的组成: struct sockaddr_in结构 ...

  9. Java网络编程入门,包含网络相关概念、InetAddress类、套接字Socket、网络上传和下载文件等

    Java学习-11-韩顺平老师 Java-网络编程入门 目录: 01-网络相关概念 02-InetAddress类 03-套接字Socket 04-网络上传和下载文件 05-UDP网络编程 网络编程相 ...

最新文章

  1. Coolite Toolkit学习笔记五:常用控件Menu和MenuPanel
  2. 蓝桥杯练习系统习题-算法提高2
  3. 【转】JMeter学习(六)集合点
  4. sql drop 简单操作(Mysql)
  5. connectionstring mysql_Entity Framework 6 自定义连接字符串ConnectionString连接MySQL
  6. 解决vs2005中文乱码问题
  7. linux socket编程:简易客户端与服务端
  8. 粉刷匠(bzoj 1296)
  9. Android中设置位移动画的停止
  10. visa虚拟卡生成器_虚拟卡有哪些功能?赶紧了解一下
  11. 《C++ Primer 第5版》源码下载地址
  12. 这是互联网变得越来越敌对的7种方式
  13. 机顶盒ttl无法输入_中兴机顶盒B8601.1T TTL后跑码无法输入指令
  14. HiC-Pro | HiC数据处理工具
  15. python小游戏课程设计报告_贪吃蛇游戏课程设计报告
  16. 禁用MacOS系统自带输入法最简单的方法
  17. 晶闸管整流桥matlab仿真,matlab仿真模型作业
  18. 在Word文档中插入Excel表格时出现:“用于创建此对象的程序是Excel。您的计算机尚未安装此程序。”试试这个方法
  19. Linux日志文件系统
  20. 第二章 一种操作系统的诞生

热门文章

  1. 微机原理-80386(3)
  2. 云台山茶旅集团带您走进湘潭市的非法集资宣传活动
  3. English Learning - L2 语音作业打卡 复习双元音 [ɔɪ] [aʊ] 代词弱读技巧 Day49 2023.4.10 周一
  4. 代理模式——虚拟代理(结构型)
  5. 使用静态内部类单例模式创建自定义线程池
  6. tomcat中间件的默认端口号_tomcat端口号修改(tomcat默认端口号是多少)
  7. 中小企业如何实施股权激励
  8. 正则基础及常用正则式
  9. katalon实现读取excel中数据并自动上传
  10. 二维 Arnold 的图像置乱加密及解密——Matlab实现