开发一段程序来模拟Socket 通讯和数据传输,socket通讯需要注意的几个问题:
- Socket API的合理使用,以及关于socket option参数的设计和优化
- socket交互中,有关阻塞/异常处理问题
- socket通讯对于server端而言,多线程或者线程池的合理使用
- 数据流成帧技术的使用
开发一段程序来模拟Socket 通讯和数据传输,socket通讯需要注意的几个问题:
package com.test.socket; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; public class SocketTestMain { private static final int port = 30008; /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Thread server = new ServerThread(); server.start(); Thread client = new ClientThread(); client.start(); Thread.sleep(2000); } static class ServerThread extends Thread { @Override public void run() { try { ServerSocket socket = new ServerSocket(); try{ //socket.setSoTimeout(20000); socket.setReuseAddress(true); socket.bind(new InetSocketAddress(port)); Socket accept = null; while ((accept = socket.accept()) != null) { accept.setTcpNoDelay(true); System.out.println("Connected Server"); Thread thread = new HandlerThread(accept); thread.start(); } }catch (Exception e) { e.printStackTrace(); }finally{ socket.close(); } } catch (Exception e) { e.printStackTrace(); } } } static class ClientThread extends Thread { @Override public void run() { try { Socket socket = new Socket(); socket.setSoTimeout(20000); //socket.setTcpNoDelay(true); socket.connect(new InetSocketAddress(port)); if (!socket.isConnected()) { System.out.println("Connect error!!"); } System.out.println("Connected"); SocketInput input = new SocketInput(socket.getInputStream()); SocketOutput output = new SocketOutput(socket.getOutputStream()); int i = 0; while (true) { if (i < 5) { SocketPacket sp = new SocketPacket(); String send = ">>>>>>" + System.currentTimeMillis(); sp.append(send.getBytes()); output.write(sp); } else { SocketPacket packet = new SocketPacket(); packet.append("quit".getBytes()); output.write(packet); socket.close(); Thread.sleep(1000); return; } SocketPacket rp = input.receive(); System.out.println("Client receive data:" + new String(rp.drawAll())); i++; Thread.sleep(2000); } } catch (Exception e) { e.printStackTrace(); } } } static class HandlerThread extends Thread { private Socket socket; HandlerThread(Socket socket) { this.socket = socket; } @Override public void run() { try { SocketInput input = new SocketInput(socket.getInputStream()); SocketOutput output = new SocketOutput(socket.getOutputStream()); while (true) { SocketPacket rp = input.receive(); String receive = new String(rp.drawAll()); System.out.println("Server receives data : " + receive); if (receive.equalsIgnoreCase("quit")) { socket.close(); return; } rp.clear(); String data = "<<<<<<<< : " + System.currentTimeMillis(); rp.append(data.getBytes()); output.write(rp); Thread.sleep(2000); } } catch (Exception e) { e.printStackTrace(); } } } }
package com.test.socket; import java.nio.ByteBuffer; public class SocketPacket { public static final String HEADER = "[MAGIC_HEADER]"; public static final int MAX_SIZE = 2048; public static final int HB_SIZE = 14;//HEADER.getBytes().length private ByteBuffer buffer = ByteBuffer.allocate(MAX_SIZE); public void append(byte[] segment){ buffer.put(segment); } /** * 返回buffer中所有的可用数据 * @return */ public byte[] drawAll(){ buffer.flip(); byte[] all = new byte[buffer.limit()]; buffer.get(all); buffer.clear(); return all; } /** * 获取buffer中可用的数据 * * @param dst * @return 获取到的byte数 */ public int draw(byte[] dst){ buffer.flip(); int remaining = buffer.remaining(); if(remaining > 0){ buffer.get(dst); buffer.compact();//压缩 buffer.position(buffer.limit());//重置position } buffer.limit(buffer.capacity());//重置limit //after this ,the buffer is ready for put. return remaining > dst.length ? dst.length : remaining; } public void clear(){ buffer.clear(); } }
package com.test.socket; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.zip.Adler32; public class SocketOutput implements Closeable { private DataOutputStream innerOutput; public SocketOutput(OutputStream stream){ innerOutput = new DataOutputStream(new BufferedOutputStream(stream,256)); } public void write(SocketPacket packet) throws Exception{ innerOutput.write(SocketPacket.HEADER.getBytes()); byte[] data = packet.drawAll(); Adler32 check = new Adler32(); check.update(data); long cs = check.getValue(); innerOutput.writeLong(cs); innerOutput.writeInt(data.length); innerOutput.write(data); innerOutput.flush(); } @Override public void close() throws IOException { innerOutput.close(); } }
package com.test.socket; import java.io.BufferedInputStream; import java.io.Closeable; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.Adler32; import java.util.zip.Checksum; public class SocketInput implements Closeable{ private DataInputStream innerInput; public SocketInput(InputStream stream){ innerInput = new DataInputStream(new BufferedInputStream(stream, 256)); } public SocketPacket receive() throws Exception{ byte[] hb = new byte[SocketPacket.HB_SIZE]; //check header innerInput.readFully(hb); String ph = new String(hb); if(!ph.equals(SocketPacket.HEADER)){ throw new IOException("Data is miss,please reconnect server!"); } //check checksum long cs = innerInput.readLong(); //check data int dl = innerInput.readInt();//data length; //get data byte[] data = new byte[dl]; innerInput.readFully(data); Adler32 check = new Adler32(); check.update(data); long ccs = check.getValue(); if(ccs != cs){ throw new IOException("Data is lost or modified,please reconnect server!"); } SocketPacket packet = new SocketPacket(); packet.append(data); return packet; } @Override public void close() throws IOException { innerInput.close(); } }
相关推荐
C写的SOCKET写的服务端程序 多线程处理客户端请求 C写的SOCKET写的服务端程序 多线程处理客户端请求 C写的SOCKET写的服务端程序 多线程处理客户端请求
C# Socket多线程编程实例-聊天程序
C# 多线程socket 实例,采用多线程设计的聊天室源码
五个package包,11个类文件 服务器入口 : com.hz.chang.server_server.ServerAction 直接运行就ok 客户端入口: ...建议导出客户端jar文件,以便在不同机器上运行客户端程序,这样容易出现那种阻塞情况.
1、运用多线程和Socket技术实现Socket Server端侦听多个客户端请求; 2、实现服务器端循环处理客户端不同请求从而实现不同测试要求,并向客户端循环发送数据; 3、实现客户端向服务器端发送不同测试命令,并接收...
Java Socket实例(服务器多线程) 自己写的代码
C#中Socket多线程编程实例.pdf
VC编写 socket 多线程 C/S双向通信
Java tcp通讯,运用多线程,一个服务端与多个客户端进行交互
java socket和多线程(Thread)实例 - JAVA SSH AJAX JS CSS - JavaEye技术网站
关于同步异步多线程SOCKET通讯,详细讲解,实例丰富,有可用的代码
C__Socket多线程编程实例 帮助了解socket 通信多线程开发
java socket 多线程文件上传下载的实例
C#Socket多线程编程实例,以C#为开发工具,实现了多线程的通信
SOCKET 多线程 C++语言 VC6.0环境
使用java socket开发的多线程文件上传下载的实例项目,多线程并发测试中可以支持200个,可能由于我电脑的配置问题,一般在并发大于200时client端可能会出现"阻塞"问题,还请大家指教
C# socket 多线程实例,客户端服务器模式。支持服务端多线程。服务端有个小问题,就是不能自行控制结束,只能control +C ,代码做参考用。
多线程 SOCKET实例 很详细 客户端和服务端 支持并发 多线程