java socketacceptor_java socket通讯

本来是打算验证java socket是不是单线程操作,也就是一次只能处理一个请求,处理完之后才能继续处理下一个请求。但是在其中又发现了许多问题,在编程的时候需要十分注意,今天就拿出来跟大家分享一下。

首先先建立一个服务端代码,运行时也要先启动此程序。

packagecom.test.some.Socket;import java.io.*;importjava.net.InetAddress;importjava.net.ServerSocket;importjava.net.Socket;importjava.net.UnknownHostException;/*** @Description: socket服务端代码

* @Author: haoqiangwang3

* @CreateDate: 2020/1/9*/

public classMySocketServer1 {//服务器监听端口

private static int port = 8081;public static void main(String[] args) throwsInterruptedException {try{//1.得到一个socket服务端

ServerSocket serverSocket = newServerSocket(port);while (true) {//2.等待socket客户端的请求。accept方法在有连接请求时才会返回

System.out.println("等待客户端请求。。。");

Socket socket=serverSocket.accept();

System.out.println("客户端请求来了。。。");//3.获取socket输入流

InputStream inputStream =socket.getInputStream();/*BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

System.out.println("接收到的请求数据为:" + bufferedReader.readLine());*/

//读取请求内容的缓冲区

byte[] bytes = new byte[1024];int length = 0;

StringBuilder sb= newStringBuilder();//获取客户端请求的内容

while ((length = inputStream.read(bytes)) != -1) {

sb.append(new String(bytes, 0, length, "utf-8"));

}

System.out.println("接收到的请求数据为:" +sb.toString());

//Thread.sleep(50000);//4.获取socket输出流

OutputStream outputStream =socket.getOutputStream();

PrintWriter printWriter= newPrintWriter(outputStream);

String backStr= "服务端接收到了请求";

printWriter.write(new String(backStr.getBytes(), "utf-8"));

printWriter.flush();//5.关闭资源//bufferedReader.close();

inputStream.close();

printWriter.close();

outputStream.close();

socket.close();

}

}catch(IOException e) {

System.err.println("socket监听失败!" +e);

}

}

}

此代码模拟了正常系统成socket服务端的方式,就是一个无限循环监听我们绑定的端口,当有客户端请求来了之后进行处理。

下面就是客户端请求代码

packagecom.test.some.Socket;importjava.io.InputStream;importjava.io.OutputStream;importjava.io.PrintWriter;importjava.net.Socket;/*** @Description: socket客户端代码

* @Author: haoqiangwang3

* @CreateDate: 2020/1/9*/

public classMySocketClient1 {//socket请求ip地址

private static String host = "127.0.0.1";//socket请求端口

private static int port = 8081;public static voidmain(String[] args) {try{//1.建立一个客户端

Socket socket = newSocket(host, port);//2.得到socket输出流

OutputStream outputStream =socket.getOutputStream();

PrintWriter printWriter= newPrintWriter(outputStream);

String sendStr= "发送数据1";//发送数据

printWriter.write(sendStr);

printWriter.flush();

socket.shutdownOutput();//3.得到socket输入流

InputStream inputStream =socket.getInputStream();

StringBuilder sb= newStringBuilder();byte[] bytes = new byte[1024];while (inputStream.read(bytes) != -1) {

sb.append(new String(bytes, "utf-8"));

}

System.out.println("接收到的返回数据为:" +sb);//4.关闭资源

printWriter.close();

outputStream.close();

inputStream.close();

socket.close();

}catch(Exception e) {

System.err.println("socket请求失败" +e);

}

}

}

客户端代码主要就是向服务端发送数据,然后等待服务端的响应,打印出服务端的响应内容。

最终打印结果如下。服务端:

6843a7fb5983d9e51dc86bc6cef424a6.png

客户端:

d19d7581ac68e11160cb3b1581fcefcd.png

首先明确几个概念,下面将会用到。

flush()方法:用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存缓冲区中,然后再用数据写到文件中。

socket.shutdownOutput()方法:他是一种单向关闭流的方法,即关闭客户端的输出流并不会关闭服务端的输出流。通过shutdownOutput()方法只是关闭了输出流,但socket仍然是连接状态,连接并未关闭。

printWriter.close()方法:如果直接关闭输入或者输出流,即:in.close()或者out.close(),会直接关闭socket。

流中的关闭顺序:一般情况下是:先打开的后关闭,后打开的先关闭。另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b,例如处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b。当然完全可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。如果将节点流关闭以后再关闭处理流,会抛出IO异常。

下面总结下我遇到的问题。

1.客户端发送数据部分的代码,printWriter.flush(); socket.shutdownOutput(); 这两句代码十分的重要,flush()方法如果不添加的话,服务端接收到的数据将为空,shutdownOutput()方法不添加的话,服务端将一直等待读取客户端的数据,不会往下进行,大家可以自测一下。我自己的理解是flush()的作用是为了把数据从内存中刷新到socket流中,shutdownOutput()方法是告诉服务端,我没有东西要传输了,所以服务端也就会停止等待读取客户端发送的内容,程序就可以继续向下走。

2.打开服务端中的sleep方法,在新建一个客户端,同时开启请求服务端,会发现服务端确实是一个连接一个连接的处理,所以这也是socket性能所在的问题。

3.如果不用字符流读取,客户端发送数据直接用outputStream.write(sendStr.getBytes());,可以发现此时不用调用flush()方法,但是socket.shutdownOutput()依然需要。这是因为直接读取到socket的输出流,并没有读到内存中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值