java Socket 客户端服务端对接正确写法(BIO)
之前在工作中写过一些Socket客户端与服务端的代码,但是当时没有时间仔细研究,只能不报错先过的态度,对其细节了解不深,写的代码有各种问题也浑然不知,只是业务量级以及对接方对接代码没有出现出格的情况所以问题不得暴露。
首先通过单线程Socket做服务端是一种BIO的做法,这种做法会导致服务端只能同时接收一笔请求,性能非常差
下面我把BIO的代码帖一下,有需要的同学可以参考
服务端
public class SocketIO {
//客户端编码,客户端发送编码与服务端一致,则服务端无需进行解码特殊处理
private static final String CLIENTENCODEING = "UTF-8";
private static final int PORT = 7777;
private static AtomicInteger count = new AtomicInteger();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("端口启动:"+PORT);
while (true) {
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
//无数据时会阻塞在这里,有数据即accept事件会触发accept方法的调用
//当一个连接进来,第二个连接进不来,因为单线程时,还阻塞在下面的read,线程无法再回到accept上继续等待
socket = serverSocket.accept();
int ccount = count.incrementAndGet();
System.out.println("新的客户端已连接,当前No."+ccount+" "+System.currentTimeMillis());
inputStream = new BufferedInputStream(socket.getInputStream());
outputStream = new BufferedOutputStream(socket.getOutputStream());
//读取正文内容
byte[] flush = new byte[1024];
int length = 0;
StringBuffer rec = new StringBuffer();
while ((length = inputStream.read(flush)) != -1) {
rec.append(new String(flush, 0, length));
}
//写法2
//客户端不通知关闭socket.shutdownOutput();时,用下面这种方法,不通知关闭read方法会死循环
//available()方法可以在读写操作前先得知数据流里有多少个字节可以读取
//但如果客户端分批发送可能有问题,可能无法获得第二批及以后的数据
//所以最好还是让客户端通知一下
// int count = 0;
// while(count == 0){
// count = inputStream.available();
// }
// byte[] flush = new byte[count];
// inputStream.read(flush);
// String rec = new String(flush, 0, count, CLIENTENCODEING);
String back = "["+ccount+"]"+UUID.randomUUID() + "";
System.out.println("收到数据:" + rec.toString() + " 即将返回数据:" + back);
//返回数据
outputStream.write(back.getBytes(), 0, back.getBytes().length);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(socket,inputStream,outputStream);
}
}
}
private static void close(Socket socket,
InputStream inputStream,
OutputStream outputStream) throws IOException {
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
if (socket != null) {
socket.close();
}
}
}
列几点需要注意的点:
1、最好通过read方法来读取客户端发来的内容,代码中available我实测客户端发送多次的情况下会丢消息,不可靠。
2、最好通过缓冲流Buffered*Stream来配合InputStream、OutputStream使用
3、write后记得flush
4、关闭流
客户端
//服务端编码
private static final String SERVERENCODEING = "UTF-8"; public static void main(String[] args){
for (int i = 0; i < 1; i++) {
new Thread(() -> {
try {
doo();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
} public static void doo() throws IOException {
Socket socket = null;
InputStream in = null;
OutputStream out = null;
String msg = "你好你好你好好好!";
try {
//发送数据
socket = new Socket("127.0.0.1", 7777);
out = new BufferedOutputStream(socket.getOutputStream());
in = new BufferedInputStream(socket.getInputStream());
out.write(msg.getBytes());
out.flush(); out.write("还有点".getBytes());
out.flush();
// //任何的输入流或输出流的close()都会造成Socket关闭 但是不关闭又导致服务端无法接收到-1
// out.close();
socket.shutdownOutput(); //读取正文内容
byte[] flush = new byte[1024];
int length = 0;
StringBuffer rec = new StringBuffer();
while ((length = in.read(flush)) != -1) {
rec.append(new String(flush, 0, length, SERVERENCODEING));//以服务端编码标准发送
}
System.out.println("客户端收到回复:" + rec.toString());
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(socket, in, out);
}
} private static void close(Socket socket,
InputStream inputStream,
OutputStream outputStream) throws IOException {
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
if (socket != null) {
socket.close();
}
}
列几点需要注意的点:
1、out.close();任何的输入流或输出流的close()都会造成Socket关闭 但是不关闭又导致服务端无法接收到-1
2、使用socket.shutdownOutput();来通知服务端发送完成
3、write后记得flush
4、关闭流
java Socket 客户端服务端对接正确写法(BIO)的更多相关文章
- 实现Java Socket 客户端服务端交互实例
SocketService.java package socket; import java.io.BufferedReader; import java.io.IOException; import ...
- Java Socket 服务端发送数据 客户端接收数据
服务端: package com.thinkgem.wlw.modules.api.test.socket; /** * @Author: zhouhe * @Date: 2019/4/8 9:30 ...
- java socket 服务端 客户端
Server package com.witwicky.socket.basicsocket; import java.io.IOException; import java.io.InputStre ...
- java scoket客户端服务端发送消息
客户端 public class User { public static void main(String[] args) { while (true) { try { Socket socket ...
- java Socket通信,客户端与服务端相互发消息
1.通信过程 网络分为应用层,http.ssh.telnet就是属于这一类,建立在传输层的基础上.其实就是定义了各自的编码解码格式,分层如下: 2.Socket连接 上述通信都要先在传输层有建立连接的 ...
- java Socket Tcp示例三则(服务端处理数据、上传文件)
示例一: package cn.itcast.net.p5.tcptest; import java.io.BufferedReader;import java.io.IOException;impo ...
- Java Socket IO(BIO、NIO)
总结下Java socket IO.首先是各种IO的定义,这个定义似乎也是众说纷纭.我按照stackoverflow上面的解释: IO有两种分法:按照阻塞或者按照同步.按照阻塞,有阻塞IO和非阻塞IO ...
- Java中使用Socket连接判断Inputstream结束,java tcp socket服务端,python tcp socket客户端
最近在试着用java写一个socket的服务器,用python写一个socket的客户端来完成二者之间的通信,但是发现存在一个问题,服务器方面就卡在读取inputsream的地方不动了,导致后面的代码 ...
- 【Socket】Java Socket基础编程
Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要讲解Socket的基础编程.Socket用在哪呢,主要用在进程间,网络间通信.本篇比较长,特别做了个目录: 一.Socket通信基 ...
随机推荐
- java整理(三)
1.继承性:继承已有的功能.使用extends关键字.class 子类 extends 父类{} 子类又被称为派生类,父类又被称为超类. 继承的限制: 1.java中,不允许多重继承,即一个子 ...
- Maven中常用插件的配置
在Maven项目的pom.xml文件中配置插件信息,使用<build></build>标签 1.配置JDK版本插件和Tomcat版本插件 <build> <! ...
- jenkins相关下载链接
Jenkins官网:https://jenkins.io/ 下载rpm安装包: https://pkg.jenkins.io http://mirrors.jenkins-ci.org/s ...
- Table AUD$
How to Truncate, Delete, or Purge Rows from the Audit Trail Table AUD$ 转到底部 PURPOSE This document e ...
- vbox 挂载共享文件时可能出现的问题以及对应的解决办法
VMBox挂载共享文件时可能出现的问题以及对应的解决办法 如果出现“未能加载虚拟光盘***.iso 到虚拟电脑的错误” : 左边一栏,右键光盘,eject,再安装
- JAVA多线程面试题目
1,java中有几种方法可以实现一个线程? 答:在Java中实现一个线程有两种方法,第一是实现Runnable接口实现它的run()方法,第二种是继承Thread类,覆盖它的run()方法.这两种方法 ...
- json数据前台解析 修改check属性用prop()
jQuery中的$.getJSON( )方法函数主要用来从服务器加载json编码的数据,它使用的是GET HTTP请求.使用方法如下: $.getJSON( url [, data ] [, succ ...
- Maven的学习资料收集--(一)环境搭建
这几天在做项目的时候用到了maven,但是自己没有从来没有接触过,所以咋网上找资料,终于找到了一下的资料,这个是别人总结的,我只是转载过来积累.请尊重原创. 官网地址:http://maven.apa ...
- LR C语言语句复习,几个简单代码
嵌套循环 Action() { int i,j; ;i<=;i++) { ) beark; else lr_output_message("i=%d",i); ;j<= ...
- InteliJ idea import project 找不到文件结构解决办法
一.按下列步骤操作: 1. 关闭IDEA, 2.然后删除项目文件夹下的.idea文件夹 3.重新用IDEA工具打开项目: 二.import新项目之后,可能需要等1 ...