网络编程:TCP编程

这是张富涛的第7篇原创

网络编程:TCP编程

根据前篇《网络编程:TCP与UDP简介及端口映射技术》介绍,网络通讯分为TCP和UDP两种方式,其中TCP方式如同打电话一般,电话接通之后,A对B进行通讯,A跟B说一k句话,如果B没听清,则A会重新说一遍。网络编程也是这样,如果发送消息的一方觉得接收消息的一方接收不到或有什么问题,则会在网络底层进行重新发送

1. Java基础类

TCP编程主要需要的两个类:

java.net.ServerSocket:
服务器端主要使用的类,用于监听特定端口,当客户端连接到了服务器端时,通过它获取连接。
java.net.Socket:
客户端和服务器端都会用到,客户端通过此类链接到服务器端,服务器端通过ServerSocket获得此类之后可进行网络通讯。由于Java的高度封装技术,我们只要简单的通过传递ip和端口号就能在客户端连接到服务器端了。

2. TCP客户端实现

在实际的网络编程中,要严格按照之前文章《网络编程:网络编程模型》中的编程模型实现每一个步骤。

我们先简单回忆一下客户端编程步骤:

  1. 建立网络连接
  2. 交换数据
  3. 关闭网络连接

首先我们需要建立网络连接,在Java中客户端通过java.net.Socket与服务器建立网络连接,我们可以在构造函数中直接传递“ip字符串”和“端口”,或传递上篇文章介绍的“InetAddress类”及“端口”:

以上代码是客户端连接服务器端的实现方式,注意其中需要处理异常,如果没有网络、或服务器端为启动则会出现异常。

一旦连接成功建立,我们即可进行数据传输,数据传输通过IO流的形式进行传递,也就是说,通过连接(Socket)获取到输出流和输入流,当需要传输数据时则向输出流里写数据,发送完毕后从输入流中读取服务器端返回的数据即可。

以上代码就是从连接获取到输出流和输入流,当我们要传送给服务器一些数据的时候,在输出流中写入数据,这些输入就会被系统发送出去给服务器端,然后我们可以从输入流中获取到服务器返回的数据。这样就完成了一次数据交换,这个步骤根据业务可以多次执行。

当然以上代码中的输出输入流都是最简单的流,我们可以通过其获取到其他我们想要的装饰流(如FileOutputStream、ObjectOutputStream等)并加以运用。

当我们完成数据通讯之后,需要释放资源,比如关闭网络连接,关闭流等操作,代码如下:

下面我们就将上述步骤整合一下并完成简单的网络客户端程序示例吧!我们要写的程序作用是向服务器端发送一个字符串“Hi,Wanfang!”,并将服务器端的反馈显示到控制台,数据交换只进行一次,当数据交换进行完成以后关闭网络连接,程序结束。实现的代码如下:

以上代码由于没有服务器端进行配合,所以目前仅是演示使用,还没办法达到实用级别。下面就让我们来介绍服务器端的写法,让这段代码输出"服务器向你说:Hi,Good boy!"吧!

3. TCP服务器端实现

我们先回忆一下服务器端的开发模型:

  1. 监听端口
  2. 获得连接
  3. 数据交换
  4. 关闭连接

首先我们进行第一步“监听端口”,实现这个步骤的代码是:

我们要注意它是“被动的监听某个端口”,所以这个方法是个阻塞方法,也就是说运行起来的时候到了这里,如果没有客户端进行连接,这段代码将不再执行下去而是继续等待。(如果要监听的端口已经被占用则会报出异常)

当有客户端连接到服务器时,我们将会通过ServerSocket获取到连接(Socket),实现这个步骤的代码是:

Socket socket= serverSocket.accept();

下面我们就可以进行第三步数据交换了,这一步骤与客户端的实现是相同的,但是它是先通过输入流获取到客户端的数据,同时通过输出流返回给客户端数据。这里不再赘述。

第四步是我们网络完需要释放资源,我们要注意这次不但要释放Socket、InputStream、OutputSteam,同时如果我们要关闭服务器端不再使用的时候,就要释放ServerSocket。

下面看一下具体实现吧!

运行的时候我们先启动服务器端,让其监听端口,再启动客户端,实际执行的时候,是服务器先监听端口,然后客户端请求连接,当连接成功时向服务器端发送信息,服务器端收到信息之后又向客户端返回信息,客户端接收信息,最后释放资源。

客户端执行结果:

服务器端执行结果:

以上代码简单实现TCP网络通讯,下面我们要往深考虑两个问题,这样有助于我们更深入的了解网络编程和在进入具体实践开发的时候能够开发出可用的代码。

4. 如何复用Socket连接

前文所述,客户端进行数据交换时可能执行多次,一般我们项目中根据业务讲可能并不会只进行一次与服务器端的交互,我们之前实现的客户端例子只是发送一次消息就关闭了,那么如何去改造代码呢?其实不难,我们只要把发送数据交换的那一块代码写一个循环就可以了。具体代码如下:

客户端设定发送多次数据,可是我们写的服务器端是接收一次就关闭连接,所以我们的服务器端也需要改造,我们将“接收数据、发送数据”的逻辑依然用代码循环多次。具体代码如下:

客户端输出结果:

服务器端输出结果:

5. 如何使服务器端支持多个客户端同时工作

服务器端是给多个客户端使用的,我们之前的代码是只能给一个客户端进行连接,这样不符合服务器端的概念,那么我们该如何改造呢?我们可以当一个客户端连接上时单独新建一个线程进行工作,利用多线程实现这个功能。

首先我们创建一个“TCPThread”线程类,让它继承“Thread”类。同时在构造方法里声明需要一个“Socket”对象,这样我们就可以在服务器端接收到连接后,把连接传给“TCPThread”进行单独处理业务了。

TCPThread类的具体实现:

同时我们需要修改一下服务器端:

这样我们的服务器端就可以处理多个客户端的连接了!但是我们可以想象一下,假如真的在实际开发中,我们这样做会有什么问题呢?

6. 线程池(Thread pool)

在真正的生产环境中,假设有足够多的客户端连接,我们没有那么多的端口,没有那么好的设备,不可能无限制的创建线程,这样的频繁创建线程的效率也比较低。这时候就要用到线程池了,线程池是先创建好一定的线程对象存在一个容器中,客户端需要连接时即可取一个线程进行连接,连接结束后会把线程放回至线程池中,这样就可以重复利用线程,并且优化内存、程序了。

那么,关于TCP编程的介绍就暂时介绍到这里,小伙伴们你学会了吗?



---------------

公众号:张富涛的学习笔记(ID:futaoNT)

知乎:张富涛

CSDN:张富涛

B站:你给的宝物

这是一个在夜晚可以靠编程拯救世界的程序员,关注他将在第一时间获悉他的知识、工作心得!

长按下图二维码关注:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值