logo头像

博学广问,自律静思

SSD8_EX2【UDP vs TCP】

这是SSD8练习的EX2,预计极客人将会写一个系列,此系列全为王柏元个人原创,更新频率会和NWPU数据库系统实验课2013级进度同步。点击标签或在本站搜索“SSD8”即可获取已更新的SSD8答案。上一练习:SSD8_EX1【Socket通信的Java实现代码】;如果你想继续跟踪SSD练习进展,建议订阅本站

问题简述

用Java写一个简单的基于C/S(客户机/服务器)模式的数据报(datagram)程序。客户端设置一个计时器,开始计时后,分别利用UDP和TCP协议向服务器发送一个字节的数据包,并等待服务器返回消息。计算平均往返时间,同时计算UDP传输过程中丢包数量并实现丢包重发。

一、用UDP实现丢包重发、丢包计数和传输计时

1.UDP服务端程序UDPServer.java

package cn.wangbaiyuan;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 基于UDP协议的服务器端,对来自客户端的数据包进行应答
* @author 王柏元
/
public class UDPServer {
/**
* 端口
*/
int port=1888;
DatagramSocket socket;
public UDPServer() throws SocketException{
socket=new DatagramSocket(port); //服务端DatagramSocket
System.out.println(“服务器启动。”);
}
public void service() throws IOException{
while(true){
DatagramPacket dp=new DatagramPacket(new byte[512],512);
socket.receive(dp); //接收客户端信息
socket.send(dp); //回复数据
}
}
public static void main(String[] args) throws SocketException, IOException {
new UDPServer().service();
}

}

2.UDP客户端程序UDPClient.java

package cn.wangbaiyuan;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
/**
* 基于UDP协议的客户端类,完成用UDP协议向服务器发送数据包
* @author 王柏元
{@linkplain http://wangbaiyuan.cn} /
public class UDPClient {
static int remotePort=1888; //服务器端口
static String remoteIp=”10.22.56.186”; //服务器IP
static DatagramSocket socket;//客户端DatagramSocket
static int times=1000;

public UDPClient() throws SocketException{

}
public static void main(String\[\] args) throws InterruptedException, SocketException {

    SocketAddress socketAddres=new InetSocketAddress(remoteIp,remotePort);
    DatagramPacket inputdp=new DatagramPacket(new byte\[512\],512);
    String s="d";
    int timeout=1;
    long toalTime=0;
    long startTime = 0;

int failTimes=0;

socket=new DatagramSocket();
socket.setSoTimeout(timeout);
byte\[\] info=s.getBytes();
DatagramPacket dp=new DatagramPacket(info,info.length,socketAddres);

for(int i=1;i<=times;i++){
    Boolean received=false;
    while(received==false){
    try {
        startTime=System.currentTimeMillis();
        socket.send(dp);
        socket.receive(inputdp);

        long endTime=System.currentTimeMillis();
        toalTime+=(endTime-startTime);
        received=true;
        System.out.println("第"+i+"次发送并接受回复成功!");

    } catch (SocketTimeoutException e) {
        failTimes++;
        received=false;
        System.out.println("第"+i+"次接收成功应答超时,尝试重发");// TODO Auto-generated catch block
    } catch (IOException e) {
        // TODO Auto-generated catch block
        System.out.println("第"+i+"次接收成功应答失败,尝试重发");
        failTimes++;
    }
    }
}
System.out.println("失败次数:"+failTimes);
float averTime=(float)toalTime/1000;
System.out.println("平均耗时:"+averTime+"豪秒");
}

}

二、用TCP实现传输计时

1.TCP服务端程序TcpServer.java

package cn.wangbaiyuan;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 基于TCP协议的服务器端,对来自客户端的数据包进行应答
* @author 王柏元
/

public class TcpServer {

ServerSocket serverSocket;
private final int PORT = 12340; // 端口

/**
* 新建EchoServer类时建立一个ServerSocket
* @throws IOException
/
public TcpServer() throws IOException {
serverSocket = new ServerSocket(PORT); // 创建服务器端套接字
System.out.println(“服务器启动。”);
}
/\
*
* 启动服务器socket服务,监听客户端消息
*/

public void servic() {
    Socket socket = null;
    while (true) {
        try {
            socket = serverSocket.accept(); // 等待并取出用户连接,并创建套接字
            // 输入流,读取客户端信息
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    socket.getInputStream(), "UTF-8"));// 涉及到安卓客户端,为留设置编码
            // 输出流,向客户端写信息
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream(), "UTF-8"));
            PrintWriter pw = new PrintWriter(bw, true); // 装饰输出流,true,每写一行就刷新输出缓冲区,不用flush
            String info = null; // 接收用户输入的信息
            while ((info = br.readLine()) != null) {
                pw.println( info); // 向客户端返回用户发送的消息,println输出完后会自动刷新缓冲区
            }
        } // 如果客户端断开连接,则应捕获该异常,但不应中断整个while循环,使得服务器能继续与其他客户端通信
        catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != socket) {
                try {
                    socket.close(); // 断开连接
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

/**
* EchoServer main静态类,启动时开启服务器端服务
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new TcpServer().servic(); // 启动服务
}
}

2.基于TCP协议的客户端类

package cn.wangbaiyuan;

import java.io.;
import java.net.
;
import java.util.Scanner;

/**
* socket TCP通信客户端类
*
* @author 王柏元
/

public class TcpClient {

/\*\*
 \* PORT 一个初始化端口
 */
static int PORT = 12340; // 连接端口
/\*\*
 \* HOST一个初始化主机名
 */
static String HOST = "10.22.56.186"; // 连接地址
/\*\*
 \* socket 客户端socket
 \* 
 */
static Socket socket;

public TcpClient() throws UnknownHostException, IOException {

}
/\*\*
 \* 实现发送消息
 */


public static void main(String\[\] args) throws UnknownHostException,
        IOException {
    BufferedReader strin = new BufferedReader(new InputStreamReader(
            System.in));
    System.out.println("请输入连接地址:");
    HOST = strin.readLine();
    System.out.println("请输入连接端口:");
    PORT = Integer.parseInt(strin.readLine());
    long toalTime=0;
    long startTime = 0;
    for(int i=1;i<=1000;i++){
        socket = new Socket(HOST, PORT); // 创建客户端套接字
        System.out.print("第"+i+"次建立链接"); 
        try {
            // 客户端输出流,向服务器发消息
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream()));
            // 客户端输入流,接收服务器消息
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            PrintWriter pw = new PrintWriter(bw, true); // 装饰输出流,及时刷新
        String msg="a";
        startTime=System.currentTimeMillis();
        pw.println(msg); // 发送给服务器端
        System.out.print(",第"+i+"次接收到"+br.readLine()); // 输出服务器返回的消息
        long endTime=System.currentTimeMillis();
        toalTime+=(endTime-startTime);


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != socket) {
                try {
                    socket.close();// 断开连接
                    System.out.println(",链接成功断开");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    float averTime=(float)toalTime/1000;
    System.out.println("平均耗时:"+averTime+"豪秒");
}

}

@极客人
极客人 commented at 2015-05-29

谢谢反馈,上传手误。tcp客户端代码已上传更新

@大力
大力 commented at 2015-05-29

为何TCP客户端和服务端一样??

@知道91博客
知道91博客 commented at 2015-05-24

又来看博主了

@song1992
song1992 commented at 2015-05-24

第一次访问,支持一下哈。