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()用于强制输出缓冲期

最新文章

  1. &quot;NHibernate.Exceptions.GenericADOException: could not load an entity&quot; 解决方案
  2. ElasticSearch配置说明
  3. Java EE开发平台随手记2——Mybatis扩展1
  4. mysql 查询某个日期时间段,每天同一时间段的数据
  5. jquery验证手机号码和固定电话号码
  6. ACM Longest Repeated Sequence
  7. CSS之圣杯布局与双飞翼布局
  8. Django views 中 View decorators
  9. VBS基础篇 - 运算符
  10. 第五十九篇、OC录制小视频
  11. 一个IP支持多个网站实例(Apache2、Ubuntu相关)
  12. MySQL创建新用户、增加账户的2种方法及使用实例
  13. Nginx并发访问优化
  14. ffmpeg结构体以及函数介绍(三)
  15. 海量信息库,查找是否存在(bloom filter布隆过滤器)
  16. springboot快速开发(简单web)
  17. 译《The Part-Time Parliament》——终于读懂了Paxos协议!
  18. Linux日志出现大量&quot;kernel: NET: Registered protocol family 36&quot;
  19. MySQL.Linux.安装
  20. Oracle- 复杂查询及总结

热门文章

  1. Codeforces 454E. Little Pony and Summer Sun Celebration
  2. codeforces 1182E Product Oriented Recurrence 矩阵快速幂
  3. GetWindowsDirectoryA and GetSystemDirectory
  4. Ubuntu图形界面和终端界面切换快捷键
  5. vs code的简单插件
  6. Python 修改在使用ddt时测试报告默认显示用例名称与预期不符
  7. Robot Framework:随机数
  8. Ubuntu下终端命令安装sublime
  9. PHP ftp_chmod() 函数
  10. 【Flutter学习】基本组件之容器组件Container