Java中提供了socket编程来构建客户端和服务器端

TCP
构建服务器端的步骤:
(1)bind:绑定端口号
(2)listen:监听客户端的连接请求
(3)accept:返回和客户端连接的实例
(4)read/write:进行读写操作,也就是和客户端进行交互
(5)close:关闭资源
Java中提供了ServiceSocket关键字来构建服务器,在Java中listen和accept合并为一个accept操作,下面通过代码演示一下这5个步骤

public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
//bind:绑定ip和端口
serverSocket.bind(new InetSocketAddress(6666));
//listen监听并且accpet返回socket实例
Socket accept = serverSocket.accept();
//通过socket拿到输入流和输出流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
PrintStream printStream = new PrintStream(accept.getOutputStream());
//读到客户端发来的数据并打印
String s = bufferedReader.readLine();
System.out.println("收到客户端的数据:"+s);
//向客户端输出数据
printStream.println("啦啦啦啦服务器回消息:"+s);
//关闭流和socket
printStream.close();
bufferedReader.close();
serverSocket.close();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
构建客户端的步骤:
(1)connect:通过IP地址和端口号连接服务器端
(2)read/write:进行读写操作,也就是和服务器端进行信息交流
(3)close:关闭资源
可以看到相比于服务器端,客户端的操作要简单很多
由于我们写的是TCP协议下的,所以要先启动服务器端,服务器端启动后,在accept会等待客户端的连接,也就是说代码在这里会阻塞住,客户端在这个时候连接就可以了。
下面用代码演示一下这几个步骤:

public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
//bind:绑定ip和端口
serverSocket.bind(new InetSocketAddress(6666));
//listen监听并且accpet返回socket实例
Socket accept = serverSocket.accept();
//通过socket拿到输入流和输出流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
PrintStream printStream = new PrintStream(accept.getOutputStream());
//读到客户端发来的数据并打印
String s = bufferedReader.readLine();
System.out.println("收到客户端的数据:"+s);
//向客户端输出数据
printStream.println("啦啦啦啦服务器回消息:"+s);
//关闭流和socket
printStream.close();
bufferedReader.close();
serverSocket.close();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这两个demo都用到了缓冲流和打印流来进行读写操作,下面看一下运行的结果

下面通过画图来描述一下这个过程

通过这幅图也会很清楚的知道三次握手和四次挥手分别发生在什么时候

下面想一个需求,如果是多个客户端和服务器端进行信息的交流怎么办?

刚才已经提到了,服务器端accpet操作是等待客户端连接的操作,那么写一个循环,每一个循环体里面有一个accept不就可以解决多个客户端连接服务器端的问题了,但是要注意一点的是accpet是一个阻塞操作,所以需要多个线程才可以,下面解释一下为什么:
首先需要明白的是只需要对服务器端进行修改即可,所以这块都是针对服务器端说的
如果只有一个线程,那么通过accpet连接上,那么这个线程还要用啦进行读写,在读写的时候也会阻塞,如果读写的时候阻塞了,那么下一个accpet就是不能正常连接的,线程就一直停到第一个连接上了,直到该连接完毕结束后才可以下一个连接,很明显这个过程是一个串行的过程,达不到所要的效果,这就需要多线程,主线程只用来保持连接(accpet),然后子线程负责和客户端进行读写交互,这样的话子线程在读写阻塞的时候是不会影响到主线程的。

下面先来看看多个客户端一个服务器端的代码:
下面的代码只展示服务器端,客户端和上面保持不变

public class MutileServer {
public static void main(String[] args) {
//创建有3个固定数量线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
try {
ServerSocket sockets = new ServerSocket(6666);
System.out.println("服务器已启动,正在等待连接");
while(true) {
Socket accept = sockets.accept();
System.out.println("客户端:"+accept.getInetAddress().getHostAddress());
executorService.execute(new MyThread(accept));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyThread implements Runnable {
private Socket socket;
private BufferedReader bufferedReader;
private PrintStream printStream;
public MyThread(Socket socket) {
this.socket = socket;
try {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printStream = new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void run() {
try {
String s = bufferedReader.readLine();
System.out.println("客户端发来消息 "+s);
printStream.println("echo"+s);
printStream.flush();
bufferedReader.close();
printStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
需要说明的几点:
(1)这块我用到了线程池,不用多次创建线程,方便统一管理并且高效。也可以单独创建多个线程,通过循环也是可以的。
(2)我写了一个MyThread类专门用来处理读写和客户端的信息交流,也就是子线程完成读写操作,主线程只用关心和服务器端的连接即可。
(3)用完资源后必须关闭,并且尽量不要抛异常,在当前方法中处理一下。

缺点
用BIO实现TCP客户端和服务器端是有缺点的,BIO是同步阻塞模型,在JDK1.4之前一直使用这种模型,但是想这样一个问题,客户端每过来一个连接服务器端就要有一个线程与之对应,那么客户端非常多的情况下,服务器端线程就会非常多,而且线程上下文切换也会成为一笔非常大的消耗,这就是BIO的缺点,如果要改善这种缺点,就需要引入NIO。

UDP
UDP不像TCP是可靠的连接,也就是会保证数据的正确送达,而UDP会以数据报的形式扩散数据,举一个很简单的例子:听广播,当节目到达时必须提前打开收音机,这样才会保证不会错过。UDP也是一样,服务器端发送数据时,客户端需要提前等着,以免错过数据。
UDP完成客户端和服务器端需要两个类:DatagramPacket和DatagramSocket
DatagramSocket是建立连接的套接字,可以理解为运送货物的码头
DatagramPacket是数据包,也就是说数据在传送过程中是被打包成了数据包,如果DatagramSocket是码头,那么DatagramPacket就是装载货物的箱子。

看一下代码:
Server:

public class Server {
public static void main(String[] args) {
//要发送的数据
String data = "数据发送了。。。";
byte[] bytes = data.getBytes();

try {
//包装成数据包的形式
DatagramPacket packet = new DatagramPacket(bytes, bytes.length,InetAddress.getByName("127.0.0.1"), 8888);
//初始化DatagramSocket
DatagramSocket socket = new DatagramSocket();
//发送数据
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Client:

public class Client {
public static void main(String[] args) {
try {
//选择监听的端口号
DatagramSocket socket = new DatagramSocket(8888);
//初始化接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//接收数据
socket.receive(packet);
//解析数据包
String s = new String(packet.getData(), 0,packet.getLength());
//打印接收到的数据
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
先启动客户端,然后再启动服务器
---------------------

C/S模型:TCP,UDP构建客户端和服务器端(BIO实现的更多相关文章

  1. osi七层模型&tcp/udp

    1.TCP/UDP协议 1.1 TCP协议 可靠,速度慢,全双工通信 建立连接三次握手,断开连接四次挥手 建立起链接之后,发送每条消息都有回执,为了保证数据的完整性,还有重传机制 数据传输:有收必有发 ...

  2. 基于UDP的客户端和服务器端的代码设计

    实验平台 linux 实验内容 编写UDP服务器和客户端程序,客户端发送消息,服务器接收消息,并打印客户端的IP地址和端口号. 实验原理 UDP是无需连接的通信,其主要实现过程如下: 同样,我们可以按 ...

  3. Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)

    Linux下测试代码: http://www.linuxhowtos.org/C_C++/socket.htm TCP模型 //TCPClient.c #include<string.h> ...

  4. TCP/UDP client/server library for Java, 最好的java语言tcp udp 服务器客户端实现库

    这个库andrdoi也可以用,而且是基于类的使用方式: 它支持类似聊天室的功能,即一个人说话,所有客户端都能收到,当然也支持点点通信.它还支持 RMI 的方式调用远程过程. https://githu ...

  5. QT 使用QUdpSocket QUdpServer UDP 建立客户端与服务器端

    1. 模拟天气监控,每隔两秒从Server发送天气信息到Client. 2. 示例代码 --------------------------- Server 端 ------------------- ...

  6. c++ 网络编程(一)TCP/UDP windows/linux 下入门级socket通信 客户端与服务端交互代码

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9601511.html c++ 网络编程(一)TCP/UDP  入门级客户端与服务端交互代码 网 ...

  7. TCP/UDP端口列表

    http://zh.wikipedia.org/wiki/TCP/UDP%E7%AB%AF%E5%8F%A3%E5%88%97%E8%A1%A8 TCP/UDP端口列表     本条目可通过翻译外语维 ...

  8. TCP/UDP 常用端口列表

    计算机之间依照互联网传输层TCP/IP协议不同的协议通信,都有不同的对应端口.所以,利用短信(datagram)的UDP,所采用的端口号码不一定和采用TCP的端口号码一样.以下为两种通信协议的端口列表 ...

  9. TCP/UDP端口列表(WIKIpedia)

    计算机之间依照互联网传输层TCP/IP协议不同的协议通信,都有不同的对应端口.所以,利用短信(datagram)的UDP,所采用的端口号码不一定和采用TCP的端口号码一样.以下为两种通信协议的端口列表 ...

随机推荐

  1. div+css布局教程系列2

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. maven配置篇

    1,windows A)安装maven之前,确认已正确安装JDK B)下载maven http://maven.apache.org/download.html C)将压缩包解压到指定目录,E:\ap ...

  3. 简单记录CentOS服务器配置JDK+Tomcat+MySQL

    项目需要部署到一台CentOS的服务器之上,之前这台服务器上面已经安装了一个Nginx和MySQL,跑的是PHP环境,有一个项目正在运行.而我们最新的项目是用Java写的,服务器是用的Tomcat,所 ...

  4. UI: 网易新闻实现

      #pragma mark-(AppDelegate.H文件)-------------------------------------------------------------------- ...

  5. ios http2客户端访问nginx失败bug

    我们将项目迁入腾讯云后,外网访问流量转发如下外网--->大禹BGP(BGPAntiDDoS)高防---->lbc(LoadBalance cluster)---->lb-----&g ...

  6. 利用插件(jQuery-ui.js)实现表格行的拖拽排序

    template 模板(html) 首先要引入jQuery-ui.js的文件.import './../../scripts/base/jquery/jquery-ui.min.js';<tab ...

  7. 使用node.js在sublime text3搭建服务器

    问题描述: 使用node.js在sublime text3中搭建好服务器后,第一次使用“ctrl+b”运行服务器没有问题,如图所示 如果想对test.js中的内容做些许修改,保存后再使用“ctrl+b ...

  8. 【插件开发】—— 5 SWT控件以及布局使用

    前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 经过前几篇的介绍,多少对SWT又有了一些认识,那么这篇继续来看一下一些控件的组合使用 ...

  9. 身份认证系统(四)OAuth2运行流程

    上一节介绍过什么是OAuth2,这节准备用生动的事例来告诉大家OAuth2运行的流程. 我们来想这样一个场景:假设我们有一个叫做万方网盘的服务是用来帮助用户存储论文文档的,我们向外提供了符合OAuth ...

  10. iOS导航栏NavigationBar的颜色,按钮和标题以及字体颜色

    首先,层级关系: leftBarButtonItem.rightBarButtonItem.title都是加在UINavigationItem上的,UINavigationItem再加在Navigat ...