【Java】Java网络编程菜鸟进阶:TCP和套接字入门
Java网络编程菜鸟进阶:TCP和套接字入门
JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)这两个数据传输协议的支持。本文开始探讨 TCP。
TCP 基础知识
在“服务器-客户端”这种架构中,服务器和客户端各自维护一个端点,两个端点需要通过网络进行数据交换。TCP 为这种需求提供了一种可靠的流式连接,流式的意思是传出和收到的数据都是连续的字节,没有对数据量进行大小限制。一个端点由 IP 地址和端口构成(专业术语为“元组 {IP 地址, 端口}”)。这样,一个连接就可以由元组 {本地地址, 本地端口, 远程地址, 远程端口} 来表示。
连接过程
在 TCP 编程接口中,端点体现为 TCP 套接字。共有两种 TCP 套接字:主动和被动,“被动”状态也常被称为“侦听”状态。服务器和客户端利用套接字进行连接的过程如下:
1、服务器创建一个被动套接字,开始循环侦听客户端的连接。
2、客户端创建一个主动套接字,连接服务器。
3、服务器接受客户端的连接,并创建一个代表该连接的主动套接字。
4、服务器和客户端通过步骤 2 和 3 中创建的两个主动套接字进行数据传输。
下面是连接过程的图解:
一个简单的 TCP 服务器
JDK 提供了 ServerSocket 类来代表 TCP 服务器的被动套接字。下面的代码演示了一个简单的 TCP 服务器(多线程阻塞模式),它不断侦听并接受客户端的连接,然后将客户端发送过来的文本按行读取,全文转换为大写后返回给客户端,直到客户端发送文本行 bye:
- public class TcpServer implements Runnable {
- private ServerSocket serverSocket;
- public TcpServer(int port) throws IOException {
- // 创建绑定到某个端口的 TCP 服务器被动套接字。
- serverSocket = new ServerSocket(port);
- }
- @Override
- public void run() {
- while (true) {
- try {
- // 以阻塞的方式接受一个客户端连接,返回代表该连接的主动套接字。
- Socket socket = serverSocket.accept();
- // 在新线程中处理客户端连接。
- new Thread(new ClientHandler(socket)).start();
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
- }
- public class ClientHandler implements Runnable {
- private Socket socket;
- public ClientHandler(Socket socket) {
- this.socket = Objects.requireNonNull(socket);
- }
- @Override
- public void run() {
- try (Socket s = socket) { // 减少代码量的花招……
- // 包装套接字的输入流以读取客户端发送的文本行。
- BufferedReader in = new BufferedReader(new InputStreamReader(
- s.getInputStream(), StandardCharsets.UTF_8));
- // 包装套接字的输出流以向客户端发送转换结果。
- PrintWriter out = new PrintWriter(new OutputStreamWriter(
- s.getOutputStream(), StandardCharsets.UTF_8), true);
- String line = null;
- while ((line = in.readLine()) != null) {
- if (line.equals("bye")) {
- break;
- }
- // 将转换结果输出给客户端。
- out.println(line.toUpperCase(Locale.ENGLISH));
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
阻塞模式的编程方式简单,但存在性能问题,因为服务器线程会卡死在接受客户端的 accept() 方法上,不能有效利用资源。套接字支持非阻塞模式,现在暂时略过。
一个简单的 TCP 客户端
JDK 提供了 Socket 类来代表 TCP 客户端的主动套接字。下面的代码演示了上述服务器的客户端:
- public class TcpClient implements Runnable {
- private Socket socket;
- public TcpClient(String host, int port) throws IOException {
- // 创建连接到服务器的套接字。
- socket = new Socket(host, port);
- }
- @Override
- public void run() {
- try (Socket s = socket) { // 再次减少代码量……
- // 包装套接字的输出流以向服务器发送文本行。
- PrintWriter out = new PrintWriter(new OutputStreamWriter(
- s.getOutputStream(), StandardCharsets.UTF_8), true);
- // 包装套接字的输入流以读取服务器返回的文本行。
- BufferedReader in = new BufferedReader(new InputStreamReader(
- s.getInputStream(), StandardCharsets.UTF_8));
- Console console = System.console();
- String line = null;
- while ((line = console.readLine()) != null) {
- if (line.equals("bye")) {
- break;
- }
- // 将文本行发送给服务器。
- out.println(line);
- // 打印服务器返回的文本行。
- console.writer().println(in.readLine());
- }
- // 通知服务器关闭连接。
- out.println("bye");
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
从 JDK 文档可以看到,ServerSocket 和 Socket 在初始化的时候,可以设定一些参数,还支持延迟绑定。这些东西对性能和行为都有所影响。后续两篇文章将分别详解这两个类的初始化。
原文链接:http://www.blogjava.net/shinzey/archive/2012/01/04/367846.html
【Java】Java网络编程菜鸟进阶:TCP和套接字入门的更多相关文章
- 网络编程(基于udp协议的套接字/socketserver模块/进程简介)
一.基于UDP协议的套接字 TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议. 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就 ...
- Java网络编程(一)Socket套接字
一.基础知识 1.TCP:传输控制协议. 2.UDP:用户数据报协议. 二.IP地址封装 1.InetAddress类的常用方法 getLocalHost() 返回本地主机的InetAddress对象 ...
- TCP/IP网络编程之优雅地断开套接字
基于TCP套接字的半关闭 Linux的close函数和Windows的closesocket函数意味着完全断开连接,完全断开连接不仅指无法传输数据,而且也不能接收数据.因此,在某些情况下,通信一方调用 ...
- 【UNIX网络编程(一)】套接字地址结构、网络字节顺序和地址转换功能
介绍:应该用在网络编程实现每个套接字地址结构.所以主套接字地址结构后前提网络计划编制,地址结构可以在两个方向上发送:从工艺到内核和内核处理.构中的二进制值之间进行转换. 大多数套接字函数都须要一个指向 ...
- windows网络编程(1)同步套接字
1.socket是应用程序与网络驱动程序的桥梁,在应用程序中创建socket,将数据交付给socket即完成数据传输,剩下的任务由socket和网络驱动程序完成: 2.套接字类型:SOCK_STREA ...
- 【Unix网络编程】chapter8基本UDP套接字编程
chapter8基本UDP套接字编程 8.1 概述 典型的UDP客户端/服务端的函数调用 8.2 recvfrom和sendto函数 #include <sys/socket.h> ssi ...
- Java之网络编程UDP和TCP
注*部分转来的 第1章 网络通信协议 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样.在计算机网 ...
- 用java网络编程中的TCP方式上传文本文件及出现的小问题
自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...
- java网络编程socket\server\TCP笔记(转)
java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04| 分类: Socket | 标签:java |举报|字号 订阅 1 TCP的开销 a ...
随机推荐
- vs2012关闭IDE硬件加速设置
对于我这样的老古董电脑是很有必要的设置! 如图所示:
- 如何优化cocos2d程序的内存使用和程序大小:第一部分_(转)
译者: 在我完成第一个游戏项目的时候,我深切地意识到“使用cocos2d来制作游戏的开发者们,他们大多会被cocos2d的内存问题所困扰”.而我刚开始接触cocos2d的时候,社区里面的人们讨论了一个 ...
- HDU 4288 线段树+离散化
题意: n个操作 在[1, 100000] 的区间上add 或del数( 必不会重复添加或删除不存在的数) sum 求出整个集合中 (下标%5 == 3 位置) 的数 的和 注意数据类型要64位 ...
- TOJ 2732存钱计划(三)(单源最短路)
存钱计划(三) 时间限制(普通/Java):1000MS/30000MS 运行内存限制:65536KByte 总提交: 18 测试通过: 16 描述 TZC的店铺比较 ...
- TopCoder SRMS 1 字符串处理问题 Java题解
Problem Statement Let's say you have a binary string such as the following: 011100011 One way to e ...
- U盘安装centos 6.4教程(总算是弄好了
参考:http://blog.chinaunix.net/uid-27666459-id-3342477.html http://www.linuxidc.com/Linux/2011-05/3569 ...
- 2进制,16进制,BCD,ascii,序列化对象相互转换
public final static char[] BToA = "0123456789abcdef".toCharArray() ; 1.16进制字符串转为字节数组 /** * ...
- HashMap深度解析(二)
本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/16890151 上一篇比较深入的分析了HashMap在put元素时的整体过 ...
- c# 访问修饰符的访问权限
1. 访问修饰符. 指定声明的类型和类型成员的可访问性. (1) public:是类型和类型成员的访问修饰符.公共访问是允许的最高访问级别.对访问公共成员没有限制. (2) private:是一个成员 ...
- php100视频原始地址列表整理:
php100视频原始地址列表整理: 教程名称 . 1:环境配置与代码调试 2:PHP的数据类型与源码调试 3:常用PHP运算类型介绍与应用 4: PHP条件语句介绍与应用 5:PHP循环语句的介绍与应 ...