java socket小实践

 

常见问题集合

http://blog.csdn.net/allanking666/article/details/5020864

使用传统套接字,进行收发数据包的小实验

客户端代码

 

		
		int port = 7777;
		int kb = 1024;
		int load = 10;
		Socket socket = new Socket("localhost", port);
		OutputStream outputStream = socket.getOutputStream();
		// 12 byte
		String msgUnit = "m";
		System.out.println(msgUnit.getBytes().length);
		StringBuffer msg = new StringBuffer();
		for (int i = 0; i < load * kb; i++) {
			msg.append(msgUnit);
		}
		System.out.println(msg.toString().getBytes().length / kb + "kb");
		long start = System.currentTimeMillis();
		DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
		dataOutputStream.writeInt(load);
		ObjectOutput objectOutput = new ObjectOutputStream(outputStream);
		List<String> list = new ArrayList<String>();
		list.add("hello world");
		objectOutput.writeObject(list);
		outputStream.write(msg.toString().getBytes());
		System.out.println(System.currentTimeMillis() - start);
		outputStream.flush();
		while (true) {

		}
	
	

(在本机C-S环境调用socket.getOutputStream().flush(),几乎没看到任何效果,是因为SocketOutputStream没有对flush方法进行实现,jvm没有对此的缓冲区。flush和Nagle's 算法无关)

使用BufferedOutputStream作为输出流则能看到效果,默认缓冲区是8kb。当write的数据不足8kb时,则需要调用flush,才会发出数据包(BufferedOutputStream通过使用buffer可以用于减少jvm和系统内核的交互次数,提高性能和吞吐量)。代码如下

 

 

BufferedOutputStream bos = new BufferedOutputStream(outputStream);
		bos.write(msgByte);
 

 

 

服务端代码

 

		
		int port = 7777;
		int kb = 1024;
		ServerSocket serverSocket = new ServerSocket(port);
		while (true) {
			Socket socket = serverSocket.accept();
			InputStream inputStream = socket.getInputStream();
			DataInputStream dataInputStream = new DataInputStream(inputStream);
			byte[] b = new byte[kb];
			int load = dataInputStream.readInt();
			ObjectInput objectInput = new ObjectInputStream(inputStream);
			List<String> list = (List<String>) objectInput.readObject();
			System.out.println(list.get(0));
			for (int i = 0; i < load; i++) {
				inputStream.read(b);
				System.out.println(new String(b));
			}

		}

 

当客户端 dataOutputStream.writeInt(load),数据包马上发出;服务端int load = dataInputStream.readInt()读取到数据。所以当多线程公用一个连接收发包,并且一个完整请求由多次write触发的时候,要防止串号。

 

如果要先把object转为byte,再用OutputStream.write(byte[] b),可以使用这种方式

 

		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutputStream);
		List<String> list = new ArrayList<String>();
		list.add("hello world");
		objectOutput.writeObject(list);
		outputStream.write(byteArrayOutputStream.toByteArray());

 也就是说byte和对象的输入输出流转化可以组合使用ByteArray*putStream和Object*putStream。数值类型和byte的转换同理可得。(http://www.360doc.com/content/07/0914/15/11586_743633.shtml

 

byte版本的客户端和服务端代码,可以解决一个完整的请求通过一次write发送,避免多线程串号。

 

客户端

 

	
		int port = 7777;
		int kb = 1024;
		int load = 10;
		Socket socket = new Socket("localhost", port);
		OutputStream outputStream = socket.getOutputStream();
		// 12 byte
		String msgUnit = "m";
		System.out.println(msgUnit.getBytes().length);
		StringBuffer msg = new StringBuffer();
		for (int i = 0; i < load * kb; i++) {
			msg.append(msgUnit);
		}
		System.out.println(msg.toString().getBytes().length / kb + "kb");
		byte[] msgByte = msg.toString().getBytes();
		long start = System.currentTimeMillis();

		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		// DataOutputStream dataOutputStream = new
		// DataOutputStream(outputStream);
		dataOutputStream.writeInt(load);
		byte[] intByte = byteArrayOutputStream.toByteArray();

		byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutputStream);
		List<String> list = new ArrayList<String>();
		list.add("hello world");
		objectOutput.writeObject(list);
		byte[] objectByte = byteArrayOutputStream.toByteArray();

		byte[] totalByte = new byte[intByte.length + objectByte.length + msgByte.length];
		System.arraycopy(intByte, 0, totalByte, 0, intByte.length);
		System.arraycopy(objectByte, 0, totalByte, intByte.length, objectByte.length);
		System.arraycopy(msgByte, 0, totalByte, intByte.length + objectByte.length, msgByte.length);
		// outputStream.write(objectByte);
		outputStream.write(totalByte);
		System.out.println(System.currentTimeMillis() - start);
		outputStream.flush();
		while (true) {

		}
	
	
 

服务端保持不变

 

		
		int port = 7777;
		int kb = 1024;
		ServerSocket serverSocket = new ServerSocket(port);
		while (true) {
			Socket socket = serverSocket.accept();
			InputStream inputStream = socket.getInputStream();
			DataInputStream dataInputStream = new DataInputStream(inputStream);
			byte[] b = new byte[kb];
			int load = dataInputStream.readInt();
			ObjectInput objectInput = new ObjectInputStream(inputStream);
			List<String> list = (List<String>) objectInput.readObject();
			System.out.println(list.get(0));
			for (int i = 0; i < load; i++) {
				inputStream.read(b);
				System.out.println(new String(b));
			}

		}
	
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(网络编程,套接字)