服务器1运行一个socket程序S1(JAVA)。
服务器2运行两个socket程序S2(DELPHI),S3(JAVA)。
S1<->S2通信端口是30001.
S1<->S3通信端口是30002.现在每天交易笔数总共大概有2500笔左右,其中2400笔是S1发送到S2处理的,100笔是S1发送到S3处理的.
目前发现程序S3运行一段时间,程序会抛出java.net.BindException: Address already in use异常。
而程序S2运行一段时间也会有异常,估计也是端口冲突导致的。我发现虽然程序是指定端口30001,30002.但是发现实际每次交易发送消息映射到操作系统的端口并不是这两个,而更像随机生成的端口。请问大家有没有遇到这种问题呢??麻烦指教一下。谢谢。
(备注,其实程序S3就是要替换程序S2的,但是目前过渡期要求并行一段时间,逐渐把交易转换到新平台程序S3)

解决方案 »

  1.   

    程序S1(TO S3)通信的大概逻辑:
    //发送消息使用消息30002
    //读取消息使用端口30003
    Socket sendSocket = new Socket(S3服务器ip,30002);
    sendSocket.setSoTimeout(15000);
    DataOutputStream dos =new DataOutputStream(sendSocket.getOutputStream());ServerSocket serverSocket = new ServerSocket(30003);
    serverSocket.setSoTimeout(15000);
    /发送消息
    dos.write(sendData);Socket clientSocket = serverSocket.accept();
    dis = new DataInputStream(clientSocket.getInputStream());
    dis.read(recData);dos.flush();
    dos.close();
    dis.close();
    sendSocket.close();
    clientSocket.close();
    serverSocket.close();程序S3通信的大概逻辑是这样的:
    ServerSocket server = new ServerSocket(30002)
    while(true)
    {
       Socket cli = server.accept();
       Socket sendSocket = null;
    try{
    sendSocket = new Socket(S2服务器ip,30003);
    }catch(Exception e){
    logger.info("重建连接异常"+e.toString());
    Thread.sleep(100);
    if(sendSocket!=null && !sendSocket.isClosed()){
    sendSocket.close();
    }
    sendSocket = new Socket(S2服务器ip,30003);
    }
         //处理交易逻辑
         Logic lt = new Logic(sendSocket);
        //线程池根据配置文件中的时间设置执行
         LogicThreadPool.execute(lt);
    }
      

  2.   

    重复绑定主要指这句话:
      ServerSocket server = new ServerSocket(30002)
    你不至于每条线程都会执行这句话吧?
    不过感觉你S3的代码很奇怪,接受了请求方的连接后:
       Socket cli = server.accept();
    对所建立Socket连接的cli啥事都没做,反而去连接S2去了,难道你S1和S2是同机部署的?
    另外不知道你是不是有个误区?一个Socket是可以同时进行读和写的,为啥你要分成两个不同端口?而且是还是通讯双方各监听一个端口?
      

  3.   

    重复绑定主要指这句话:
      ServerSocket server = new ServerSocket(30002)
    你不至于每条线程都会执行这句话吧?
    ------------------------------------------------------
    是的,每条线程都会执行的Socket cli = server.accept();
    -------------------------------------------------------
    有用的,,我没写出来。。会读取发送过来的消息的。。另外不知道你是不是有个误区?一个Socket是可以同时进行读和写的,为啥你要分成两个不同端口?而且是还是通讯双方各监听一个端口?---------------------------------------------------------
    我知道的,但是因为开始时S1,S3是同机部署,所以这样会有问题。。所以才改成这样的刚开始测试时,量少的时候没发现问题,部署后交易量大了才暴露这个问题
      

  4.   


    这绝对的不合理你应该只有一个线程负责监听,然后启动其它线程来提供服务,而不是每个线程都去执行这句话。但我看你3楼的代码,应该是循环中创建子线程(线程池)来处理Socket啊这里给个参考:import java.io.*;
    import java.net.*;
    import java.util.*;public class EchoServer {
        public static final int PORT = 10000;    public static void main(String[] args) throws Exception {
            ServerSocket serverSocket = new ServerSocket(PORT);
            try {
                while (true) {
                    System.out.println("服务端就绪,等待客户端连接");                // 侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
                    Socket socket = serverSocket.accept();
                    System.out.println("有客户端连接上来了,已建立Socket链接");                EchoServerWorker worker = new EchoServerWorker(socket);
                    System.out.println("启动工作线程");
                    new Thread(worker).start();
                }
            } finally {
                serverSocket.close();
            }
        }
    }class EchoServerWorker implements Runnable {
        private Socket socket; // 工作线程所服务的目标Socket    EchoServerWorker(Socket socket) {
            this.socket = socket;
        }    public void run() {
            try {
                try {
                    // 准备输入输出端口
                    Scanner sc = new Scanner(socket.getInputStream());
                    OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
                    System.out.println("Socket for " + socket.getPort() + " started.");
                    
                    // 读取信息并直接返回,这里按行读取(\n)
                    String str;
                    while ((str = sc.nextLine()) != null) {
                        System.out.println("【From Client】" + str);
                        out.write(str + "\n");
                        out.flush();
                    }
                } finally {
                    socket.close();
                    System.out.println("Scoket for " + socket.getPort() + " closed.");
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }}