datagramsocketcommclient.java
来自「cqME :java framework for TCK test.」· Java 代码 · 共 330 行
JAVA
330 行
/* * $Id$ * * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */package com.sun.tck.j2me.services.commService.clients;import java.io.IOException;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.net.DatagramSocket;import java.net.DatagramPacket;import java.net.InetAddress;import com.sun.tck.j2me.communication.CommunicationClient;import com.sun.tck.j2me.services.commService.DatagramSocketCommServiceUtils;/** * DatagramSocket based DTF Communication Client for CDC/J2SE, with * limited send and receive capability. */public class DatagramSocketCommClient extends DatagramSocketCommServiceUtils implements CommunicationClient { protected static final int DEFAULT_CLIENT_NUM_OF_RETRIES = 12; protected static final String NUM_OF_RETRIES_OPTION = "numberOfRetries="; protected static final String PORT_TO_BIND_OPTION = "portToBind="; private InetAddress serverAddress; private String serverHost; private int serverPort; private String connID = ""; private int connIDBytesLength = 0; private int packetNum = 0; private int numOfRetries = DEFAULT_CLIENT_NUM_OF_RETRIES; private int portToBind = 0; // Bind to any free port public DatagramSocketCommClient() { verboseln("Constructed new DatagramSocketCommClient"); } public void init(String serverLocator, String connID, String[] args) { this.connID = connID; // reset server address serverAddress = null; decodeAllArgs(args); verboseln("DatagramSocketCommClient.init serverLocator " + serverLocator); verboseln("DatagramSocketCommClient.init connID " + connID); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); try { dos.writeUTF(connID); dos.close(); connIDBytesLength = dos.size(); } catch (IOException ioe) { verbosetrace(ioe); throw new IllegalArgumentException("DatagramSocketCommClient.init: " + "failed to calculate length of " + "connID converted to " + "byte array due to " + ioe); } String[] hostport = getHostAndPortFromURL(serverLocator); serverHost = hostport[0]; String serverPortString = hostport[1]; serverPort = -1; try { serverPort = Integer.parseInt(serverPortString); } catch (NumberFormatException nfe) { throw new IllegalArgumentException("DatagramSocketCommClient.init: " + "invalid serverLocator " + serverLocator + " " + nfe); } verboseln("DatagramSocketCommClient.init: host " + serverHost); verboseln("DatagramSocketCommClient.init: port " + serverPort); } protected void processArg(String arg) { if (arg.startsWith(NUM_OF_RETRIES_OPTION) && arg.length() > NUM_OF_RETRIES_OPTION.length()) { String numOfRetriesString = arg.substring(NUM_OF_RETRIES_OPTION.length()); try { numOfRetries = Integer.parseInt(numOfRetriesString); if (numOfRetries < 1) { throw new IllegalArgumentException("Incorrect number of " + "retries specified: " + numOfRetriesString); } } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Incorrect number of " + "retries specified: " + numOfRetriesString); } } else if (arg.startsWith(PORT_TO_BIND_OPTION) && arg.length() > PORT_TO_BIND_OPTION.length()) { String portToBindString = arg.substring(PORT_TO_BIND_OPTION.length()); try { portToBind = Integer.parseInt(portToBindString); if (numOfRetries < 0) { throw new IllegalArgumentException("Incorrect port to " + "bind specified: " + portToBindString); } } catch (NumberFormatException nfe) { throw new IllegalArgumentException("Incorrect port to " + "bind specified: " + portToBindString); } } else { super.processArg(arg); } } public synchronized byte[] send(byte[] packet) throws IOException { if (packet == null) throw new IllegalArgumentException( "DatagramSocketCommClient: Attempt to send null packet."); if (packet.length > getSendLimitSize()) { throw new IllegalArgumentException( "DatagramSocketCommClient: Attempt to send" + " an oversized packet."); } if (serverAddress == null) { serverAddress = InetAddress.getByName(serverHost); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); // prepare DatagramPacket to be sent // first 4 bytes is packet number dos.writeInt(packetNum); // write connID dos.writeUTF(connID); // write data dos.write(packet, 0, packet.length); dos.close(); byte[] buf = baos.toByteArray(); DatagramPacket packetToSend = new DatagramPacket(buf, buf.length, serverAddress, serverPort); // prepare DatagramPacket to be received byte[] buf2 = new byte[packetSize]; DatagramPacket packetToReceive = new DatagramPacket(buf2, buf2.length); DatagramSocket dts = null; try { // The following is equivalent to DatagramSocket(0), but // DatagramSocket(int port) specification does not specify behavior when // port is 0. Replace it by DatagramSocket() to be safe. // // dts = new DatagramSocket(portToBind); // create a DatagramSocket which binds to a system chosen port dts = new DatagramSocket(); dts.setSoTimeout(socketTimeout); int rcvBufSz = dts.getReceiveBufferSize(); int sndBufSz = dts.getSendBufferSize(); verboseln("DatagramSocketCommClient.send: created socket"); verboseln("DatagramSocketCommClient.send: socket's local address " + dts.getLocalAddress()); verboseln("DatagramSocketCommClient.send: socket's receive buffer " + rcvBufSz); verboseln("DatagramSocketCommClient.send: socket's send buffer " + sndBufSz); if (rcvBufSz < (packetSize + 28) || sndBufSz < (packetSize + 28)) { verboseln("Warning size of buffers might be not enough: " + "Receive - " + rcvBufSz + ", Send - " + sndBufSz); } for (int numAttempts = 0; numAttempts < numOfRetries; numAttempts++) { try { verboseln("Sending packet number " + packetNum + " to " + packetToSend.getAddress()); dts.send(packetToSend); } catch (IOException ioe) { verboseln("IOException in send" + ioe); continue; } // This while is needed to read all available datagrams // before resending data. Server is passive, it only sends // one datagram in response to every received datagram. while (true) { try { packetToReceive.setLength(packetSize); dts.receive(packetToReceive); verboseln("Got out of dts.receive(packetToReceive)"); } catch (IOException ioe) { verboseln("IOException in receive " + ioe); break; } InetAddress senderAddress = packetToReceive.getAddress(); verboseln("Received packet from " + senderAddress); byte[] data = packetToReceive.getData(); if (data.length < 4) { verboseln("Panic, packet's data length is " + data.length); continue; } // need to take length of Datagram into account because // getData() returns NOT the content of the datagram, // but rather the whole buffer ByteArrayInputStream bais = new ByteArrayInputStream( data, packetToReceive.getOffset(), packetToReceive.getLength()); DataInputStream dis = new DataInputStream(bais); int receivedPacketNum = dis.readInt(); verboseln("Number of received packet is " + receivedPacketNum); if (receivedPacketNum == packetNum) { byte[] ret = new byte[dis.available()]; dis.readFully(ret); return ret; } else { verboseln("WARNING: Received packet has unexpected number " + receivedPacketNum + ", expected " + packetNum); } } } throw new IOException("Failed to send packet " + numOfRetries + " times."); } finally { packetNum++; if (dts != null) { dts.close(); } verboseln("End of send's finally"); } } public int getSendLimitSize() { return packetSize - 4 - connIDBytesLength; } public int getRcvLimitSize() { return packetSize - 4 - connIDBytesLength; } private static String[] getHostAndPortFromURL(String url) throws IllegalArgumentException { // parse url into hostname and port // expecting something like http://host:port or // datagram://host:port. Class URL can not parse neither // http://host:port nor datagram://host:port under CDC. Class // URI is not available under CDC so parse manually. int pos = url.indexOf("://"); int pos2 = url.lastIndexOf(":", url.length() - 1); if (pos == -1 || pos2 == -1 || pos2 == url.length() - 1 || pos2 <= pos + 3 || url.indexOf(']') > pos2) { throw new IllegalArgumentException("Cannot determine host and/or " + "port from URL " + url ); } try { String hostpart = url.substring(pos + 3, pos2); String portpart = url.substring(pos2 + 1); if (hostpart.startsWith("[")) { // This is an RFC 2732 address int pos3 = hostpart.indexOf(']'); hostpart = hostpart.substring(1, pos3); } return new String[] {hostpart, portpart}; } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException("Errors occurs when parsing URL " + url + " : " + e.getMessage()); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?