廖雪峰Java13网络编程-1Socket编程-2TCP编程
2024-10-07 20:58:53
1. Socket
在开发网络应用程序的时候,会遇到Socket这个概念。
Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。
Socket/TCP/部分IP都是由操作系统提供的。不同的编程语言只是提供了对操作系统调用的加单封装,例如Java提供的几个Socket相关的类就封装了操作系统提供的接口。
为什么需要Socket?
因为仅仅通过IP地址进行通信还不够,同一台计算机同一时间会运行多个网络程序。当计算机收到一个数据包的时候,只有IP地址是没法判断应该发送给哪个应用程序的,所以操作系统抽象出Socket接口。每个应用程序需要对应不同的Socket,可以把Socket简单理解为IP地址+端口号。
端口号是操作系统分配的,是在0-65535之间的数字
- <1024是特权端口,需要管理员权限
- >1024的端口可以由任意应用程序打开
2. Socket使用
Socket编程模型需要实现服务器端与客户端,因为2个应用程序通信的时候不仅需要对方的IP,还需要知道对方的端口号。所以服务器端必须先固定一个端口号,例如80。客户端在发起请求的时候,会直接请求80端口,同时告知自己的端口,这样双方就可以通过Socket进行通信了。
客户端的编程:
Socket sock = new Socket(InetAddress,port);//连接到远程服务器的指定端口
InputStream in = sock.getInputStream();//获取到输入和输出流
OutputStream out = sock.getOutputStream();
//读写字节流
服务器端:
ServerSocket ss = new ServerSocket(port); //监听指定端口号
Socket sock = ss.accept();
InputStream in = sock.getInputStream();
OutputStream out = sock.getOutputStream();
//读写字节流
TCPClient.java
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class TCPClient {
public static void main(String[] args) throws IOException{
InetAddress addr = InetAddress.getLoopbackAddress(); //获取本机的InetAddress,通常是127.0.0.1
try(Socket sock = new Socket(addr,9090)){ //打开远程连接
try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(),StandardCharsets.UTF_8))){//BufferedReader类就是一个包装类,它可以包装字符流,将字符流放入缓存里,到缓存满了或者执行flush的时候,再读入内存,可以提交读的效率。
try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){
writer.write("time\n");
writer.flush();//强制把缓存区的内容发送出去
String resp = reader.readLine();
System.out.println("Response:"+resp);
}
}
}
}
}
TCPServer.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalTime;
public class TCPServer {
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(9090);
System.out.println("TCP Server ready:");
Socket sock = ss.accept();
try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(),StandardCharsets.UTF_8))){
try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){
String cmd = reader.readLine(); //获取客户端传过来的数据
if("time".equals(cmd)){
writer.write(LocalTime.now()+"\n");
writer.flush();
}
}
}
sock.close();
ss.close();
}
}
先运行服务器端,再运行客户端
3. 总结:
TCP编程模型:
- 客户端使用Socket(InetAddress,port)打开Socket
- 服务器用ServerSocket监听端口
- 服务器用accept接收连接并返回Socket
- 双方通过Socket打开InputStream/OutputStream读写数据
- flush()用于强制输出缓冲期
最新文章
- ";NHibernate.Exceptions.GenericADOException: could not load an entity"; 解决方案
- ElasticSearch配置说明
- Java EE开发平台随手记2——Mybatis扩展1
- mysql 查询某个日期时间段,每天同一时间段的数据
- jquery验证手机号码和固定电话号码
- ACM Longest Repeated Sequence
- CSS之圣杯布局与双飞翼布局
- Django views 中 View decorators
- VBS基础篇 - 运算符
- 第五十九篇、OC录制小视频
- 一个IP支持多个网站实例(Apache2、Ubuntu相关)
- MySQL创建新用户、增加账户的2种方法及使用实例
- Nginx并发访问优化
- ffmpeg结构体以及函数介绍(三)
- 海量信息库,查找是否存在(bloom filter布隆过滤器)
- springboot快速开发(简单web)
- 译《The Part-Time Parliament》——终于读懂了Paxos协议!
- Linux日志出现大量";kernel: NET: Registered protocol family 36";
- MySQL.Linux.安装
- Oracle- 复杂查询及总结
热门文章
- Codeforces 454E. Little Pony and Summer Sun Celebration
- codeforces 1182E Product Oriented Recurrence 矩阵快速幂
- GetWindowsDirectoryA and GetSystemDirectory
- Ubuntu图形界面和终端界面切换快捷键
- vs code的简单插件
- Python 修改在使用ddt时测试报告默认显示用例名称与预期不符
- Robot Framework:随机数
- Ubuntu下终端命令安装sublime
- PHP ftp_chmod() 函数
- 【Flutter学习】基本组件之容器组件Container