网络编程之二:java.net包的Socket和SocketServer
来源:互联网 发布:空调结构设计知乎 编辑:程序博客网 时间:2024/04/28 21:50
本博文简要阐述java.net包下的基于TCP/IP的Socket编程以及其源码分析
public static voidmain(String args[]) throws IOException { ServerSocket server = null; server =new ServerSocket(4444);// 设置server的端口 Socketsocket = null; int number= 0; booleanflag = true; try{ while (flag) { socket = server.accept();//监听连接,方法阻塞,能够建立多个长连接 number++; createHandlerThread(socket,number);// 为每一个连接建立线程 } } finally{ server.close(); } }
private static voidcreateHandlerThread(Socket socket, int number) { DataAcceptServer das = new DataAcceptServer(); Handlerhandler = das.new Handler(socket, number); Thread t =new Thread(handler); t.start(); }
public class Handlerimplements Runnable { privateSocket socket = null; privateint number = 0;
publicHandler(Socket socket, int number) { this.socket = socket; this.number = number; }
@Override publicvoid run() { System.out.println("get the connetion withclient" + number); BufferedReader in = null; PrintWriter out = null; try { in = new BufferedReader(newInputStreamReader( socket.getInputStream(), "UTF-8")); //获取socket的接收流 out = new PrintWriter(newOutputStreamWriter( socket.getOutputStream(), "UTF-8"));//获取socket的发送流 } catch (IOException e) { e.printStackTrace(); } String getline = null; boolean end = false; while (!end) { try { getline =in.readLine(); // 获取消息 } catch (IOException e){ e.printStackTrace(); break; } System.out.println("getmessage from client" + number + " :" + getline); out.write("ok\n"); //返回ok out.flush(); if (getline.equals("byebye")){ end =true; } } try { in.close(); out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("release the connetion withclient" + number); } }
public static voidmain(String args[]) throwsUnknownHostException, IOException { Socketsocket = new Socket("127.0.0.1", 4444); //设置server的ip和端口 //socket.setSoTimeout(10000);//设置超时时间 BufferedReader sin = new BufferedReader(newInputStreamReader( System.in)); PrintWriter out = new PrintWriter(newOutputStreamWriter( socket.getOutputStream(),"UTF-8"));//获取socket的发送流 BufferedReader in = new BufferedReader(newInputStreamReader( socket.getInputStream(),"UTF-8"));//获取socket的接收流 Stringreadline = null; readline =sin.readLine(); while(!readline.equals("byebye")) {//以byebye终止连接 out.println(readline); out.flush(); System.out.println("Client:" +readline); System.out.println("Server:" +in.readLine()); readline = sin.readLine(); } out.close(); in.close(); socket.close(); }
写网络编程这一章,初衷是为了讲诉HttpClient、Jetty、Netty的使用心得,NIO和BIO的比较,Thrift和Avro等,无奈今天被合作伙伴鄙视了,他看到我用了Apache的Httpclient(C)+Jetty(S),说:你只不过是传一些数据,用Socket多简单迅速,我们的量一天十几T,难怪我这边一堆的timeout。后来他告诉我他用得是“c调用linux的Socket接口”写的自己的库,很骄傲表示速度杠杠的(工程量变大是一弊端),于是我也看了一下java.net基础包下的东西,会有两章,本章主要是将应对TCP/IP的Socket部分。
java.net包含以下几类:DatagranSocket一类,Socket/ServerSocket一类,InetXAddress一类,URL相关一类以及其他,本章主要讲诉的是Socket/ServerSocket
Socket编程,无非就是一个Socket(C)去连接一个ServerSocket(S),所以编写了两个简单的程序并进行分析,功能有一个DataAcceptServer,可以创建4444端口,能够最多接受50个连接;两个DataSender,创建长连接,知道发送byebye为止。为方便,使用UTF-8字符流。程序如下:
//Server
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclass DataAcceptServer {
}
ServerSocket类在java.net下并不起眼,也不完成主要的工作(SocketImpl的子类PlainSocketImpl和它的子类SocksSocketImpl完成了最重要的工作)
第一步:ServerSocket server = newServerSocket(4444)
1、转化为ServerSocket(int port, intbacklog, InetAddress bindAddr)构造方法,port(必需)+ 最大连接数(默认50)+服务地址(默认本机)。ip+端口会以InetSocketAddress类形式存在。
2、SecurityManager security =System.getSecurityManager();security会去检测此port是否可用
3、bind(),由PlainSocketImpl中的native方法socketBind来完成,也就是使用系统调用来完成创建和绑定端口的工作
4、listen(),由PlainSocketImpl中的native方法socketListen来完成,也就是使用系统调用来完成设置最大连接数,创建queuefor incoming connectionindications(a request toconnect),其中的count参数就是最大连接数。如果thequeue满了了话,将会refuse后面的connection
第二步:Socket socket= server.accept();
1、accept(SocksSocketImpl s),是一个阻塞方法,由PlainSocketImpl的native方法socketAccept来完成,也就是使用系统调用来监听是否有连接进来,直到有一个连接
2、响应连接,创建Socket对象,同时赋予其一个非常最要的对象SocksSocketImpl,它完成了我们所见到socket对象的所有的工作。
第三步:socket.getOutputStream()和socket.getInputStream()来获取SocksSocketImpl对象的输入输出流。接下来的工作就使用流来处理了。
//client
importjava.io.BufferedReader;
import java.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
importjava.net.UnknownHostException;
public class DataSender {
}
Socket类就更为简单了,但是背后的秘密也是值得挖掘,他完成的主要是创建对某个服务的连接,并传输数据或者命令
第一步:Socketsocket = new Socket("127.0.0.1", 4444);
1、首先为自己创建一个SocksSocketImpl对象
2、bind(),由PlainSocketImpl中的native方法socketBind来完成,也就是使用系统调用来完成绑定端口的工作
3、connect(),由SocksSocketImpl对象的connect来进入(因为涉及到安全验证和各种不同的connect方法如代理等),最终由PlainSocketImpl的socketConnect来完成,也是使用系统调用来完成connect的工作。
第二步:socket.getOutputStream()和socket.getInputStream()来获取SocksSocketImpl对象的输入输出流。接下来的工作就使用流来处理了。
看到这里,其实socket编程最核心的工作都并不是由它本身来完成,而是使用非java方法来完成,JNI调用系统C库(会在之后的章程介绍),因此我认为,在承受范围之内,慢并不是java的错,而是我实现的有问题。
最后总结一张图:
由于博主知识有限,如有误,请指正点评,欢迎交流
0 0
- 网络编程之二:java.net包的Socket和SocketServer
- Java网络编程之Socket与SocketServer
- 网络编程2之Socket简介和java.net包
- Python网络通信之黏包问题(五)基于SocketServer模块和socket模块
- python Socket编程(二)----SocketServer
- python socket编程(二)--SocketServer模块
- python网络编程之TCP通信实例和socketserver框架
- .net Socket 网络编程(二)
- 网络编程之三:java.net包的DatagramSocket和DatagramPacket
- Python基础篇之Socket编程 SocketServer
- java网络socket编程(二)之Socket客户端
- python 网络编程之socketserver模块
- Java编程思想之网络编程(二)套接字Socket
- Java Socket网络编程二
- Java Socket网络编程二
- Java网络编程之Socket的使用
- Java网络编程之Socket通信(二)
- python网络编程SocketServer
- linux上常用的命令
- 黑马程序员--22--高新技术(三)
- C#值传递与引用传递
- 暑期个人赛--第一场--E
- 网络编程之一:网络编程的大门
- 网络编程之二:java.net包的Socket和SocketServer
- 网络编程之三:java.net包的DatagramSocket和DatagramPacket
- 单例传值
- 分布式系统之一:分布式系统的挑战
- RPC/RMI之一:RPC简介
- RPC/RMI之二:XMLRPC
- RPC/RMI之三:JSONRPC
- 分布式系统之二:CAP定理
- 分布式系统之三:CAP定理的实践