第一步 充分理解Socket

1.什么是socket

所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

重要的Socket API:

java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。

.Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。

.getInputStream方法获得网络连接输入,同时返回一个IutputStream对象实例,。

.getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

2.如何开发一个Server-Client模型的程序

开发原理:

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。

客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

第二步 多个客户同时连接

在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序除了能处理用户的输入信息,还必须能够同时响应多个客户端的连接请求。在java中,实现以上功能特点是非常容易的。

设计原理:

主程序监听一端口,等待客户接入;同时构造一个线程类,准备接管会话。当一个Socket会话产生后,将这个会话交给线程处理,然后主程序继续监听。运用Thread类或Runnable接口来实现是不错的办法。

建立服务器:

import java.io.*;
import java.net.*;
public class Server extends ServerSocket{
    
    private static final int SERVER_PORT = 10000;
    
    public Server() throws IOException{
        super(SERVER_PORT);
        
        try{
            while (true){
                Socket socket = accept();
                new CreateServerThread(socket);
            }
        }catch (IOException e){
            
        }finally{
            close();
        }
    }
    
    //--- CreateServerThread
    class CreateServerThread extends Thread{
        
        private Socket client;
        private BufferedReader in;
        private PrintWriter out;
        
        public CreateServerThread(Socket s) throws IOException{
            client = s;
            in = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF8"));
            out = new PrintWriter(client.getOutputStream(), true);
            
            start();
        }
        public void run(){
            try{
                String line = in.readLine();
                while (!line.equals("bye")){
                    String msg = createMessage(line);
                    out.println(msg);
                    line = in.readLine();
                }
                out.println("--- See you, bye! ---");
                client.close();
            }catch (IOException e){
                
            }
        }
        private String createMessage(String line){
            int len = line.length();
            return len + " server";
        }
    }
    
    public static void main(String[] args) throws IOException{
        new Server();
    }
}

建立客户端:由于 java 的跨平台性  这里将两个 java  和 ruby

java:

import java.io.*;
import java.net.*;
public class Client{
    Socket socket;
    BufferedReader in;
    PrintWriter out;
    public Client(){
        try{
            socket = new Socket("127.0.0.1", 10000);

BufferedReader line = new BufferedReader(new InputStreamReader(System.in,"UTF8"));
            out = new PrintWriter(socket.getOutputStream(),true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
            
            String readline;
            readline=line.readLine();
            
            while(!readline.equals("bye")){
                out.println(readline);
                out.flush();
                System.out.println("Client:"+readline);
                System.out.println("Server:"+in.readLine());
                readline=line.readLine();
            }

line.close();
            out.close();
            in.close();
            socket.close();
         }catch (IOException e){}
    }
    public static void main(String[] args){
        new Client();
    }
}

//这个客户端连接到地址为xxx.xxx.xxx.xxx的服务器,端口为10000,并从键盘输入一行信息,发送到服务器,然后接受服务器的返回信息,最后结束会话。

ruby:

1.

某jar包有多个classw文件包含了main 函数,

需要在外部用java命令的bat文件来执行这个jar包的某个class文件的main函数.

java -classpath jar名字.jar 包名.类名

2.ruby

require 'socket'
class Client

s = TCPSocket.new '127.0.0.1', 10000

1.upto(10) do |n|
    s.send("hello #{n}\n",0)
    s.flush
  end

while line = s.gets # Read lines from socket
    puts line         # and print them
  end
  s.close

end

第三步 实现信息共享:在Socket上的实时交流

网络的伟大之一也是信息共享,Server可以主动向所有Client广播消息,同时Client也可以向其它Client发布消息。下面看看如何开发一个可以实时传递消息的程序。

设计原理:

服务器端接受客户端的连接请求,同时启动一个线程处理这个连接,线程不停的读取客户端输入,然后把输入加入队列中,等候处理。在线程启动的同时将线程加入队列中,以便在需要的时候定位和取出。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
public class Server1 extends ServerSocket{
    
    private static ArrayList User_List = new ArrayList();
    private static ArrayList Threader = new ArrayList();
    private static LinkedList Message_Array = new LinkedList();
    private static int Thread_Counter = 0;
    private static boolean isClear = true;
    protected static final int SERVER_PORT = 10000;
    protected FileOutputStream LOG_FILE = new FileOutputStream("d:/connect.log", true);
    
    public Server1() throws FileNotFoundException, IOException{
        super(SERVER_PORT);
    
        new Broadcast();
        
        //append connection log
        Calendar now = Calendar.getInstance();
        String str = "[" + now.getTime().toString() + "] Accepted a connection1512";
        byte[] tmp = str.getBytes();
        LOG_FILE.write(tmp);
        try{
            while (true){
                Socket socket = accept();
                new CreateServerThread(socket);
            }
        }finally{
            close();
        }
    }
    
    public static void main(String[] args) throws IOException{
        new Server1();
    }
    
    //--- Broadcast
    class Broadcast extends Thread{
        
        public Broadcast(){
            start();
        }
        public void run(){
            while (true){
                if (!isClear){
                    String tmp = (String)Message_Array.getFirst();
                    for (int i = 0; i < Threader.size(); i++){
                        CreateServerThread client = (CreateServerThread)Threader.get(i);
                        client.sendMessage(tmp);
                    }
                    Message_Array.removeFirst();
                    isClear = Message_Array.size() > 0 ? false : true;
                }
            }
        }
    }
    
    //--- CreateServerThread
    class CreateServerThread extends Thread{
        
        private Socket client;
        private BufferedReader in;
        private PrintWriter out;
        private String Username;
    
        public CreateServerThread(Socket s) throws IOException{
            client = s;
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            out = new PrintWriter(client.getOutputStream(), true);
            out.println("--- Welcome to this chatroom ---");
            out.println("Input your nickname:");
            start();
        }
        
        public void sendMessage(String msg){
            out.println(msg);
        }
        
        public void run(){
            try{
                int flag = 0;
                Thread_Counter++;
                String line = in.readLine();
                while (!line.equals("bye")){
                    if (line.equals("l")){
                        out.println(listOnlineUsers());
                        line = in.readLine();
                        continue;
                    }
                    
                    if (flag++ == 0){
                        Username = line;
                        User_List.add(Username);
                        out.println(listOnlineUsers());
                        Threader.add(this);
                        pushMessage("[< " + Username + " come on in >]");
                    }else{
                        pushMessage("<" + Username + ">" + line);
                    }
                    line = in.readLine();
                }
                out.println("--- See you, bye! ---");
                client.close();
            }catch (IOException e){
                
            }finally{
                try{
                    client.close();
                }catch (IOException e){}
                Thread_Counter--;
                Threader.remove(this);
                User_List.remove(Username);
                pushMessage("[< " + Username + " left>]");
            }
        }
    
        private String listOnlineUsers(){
            String s ="-+- Online list -+-1512";
            for (int i = 0; i < User_List.size(); i++){
                s += "[" + User_List.get(i) + "]1512";
            }
            s += "-+---------------------+-";
            return s;
        }
        private void pushMessage(String msg){
            Message_Array.addLast(msg);
            isClear = false;
        }
    }
}

这就是程序运行后,多用户登陆并且输入信息后的屏幕。实现了信息的实时广播。用户输入"l"就可以列出在线人员表。

1 封装一个 jar 包
2 java xxx.jar 开启一个 socket server
3 socket 服务接受一个字符串,返回字符串的长度给客户端
3 写一个 ruby client 看看是否可以正常访问 socket

 
 

JAVA Socket(多个客户同时连接,信息共享) client (java/ruby)的更多相关文章

  1. Java Socket编程如何建立两者关系

    转自:http://developer.51cto.com/art/201003/190582.htm Java Socket编程需要大家详细的学习,有关的技术一直在不断的更新.那么要如何才能掌握好有 ...

  2. java Socket 长连接 心跳包 客户端 信息收发 demo

    今天写了个socket的测试小程序,代码如下 import java.io.IOException; import java.io.InputStream; import java.io.Output ...

  3. java socket通讯(二)处理多个客户端连接

    通过java socket通讯(一) 入门示例,就可以实现服务端和客户端的socket通讯,但是上一个例子只能实现一个服务端和一个客户端之间的通讯,如果有多个客户端连接服务端,则需要通过多线程技术来实 ...

  4. 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)

    目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...

  5. 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

    在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...

  6. 运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接

    运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接 最近在项目中可能要用到socket相关的东西来发送消息,所以初步研究了下socket的TC ...

  7. JAVA Socket连接服务器时可能抛出的异常

    1.UnknownHostException:host(非ip)无法识,就会报该异常,www.google.com.hk这个虽然也ping不通,但是不会报该错,因为他是一个确实存在的域名.他会报Con ...

  8. Java 使用 Socket 实现客户端和服务器的信息交互

    服务器 public class Server{ private ServerSocket serverSocket; private Socket socket; private BufferedR ...

  9. Java Socket通信读取相关信息代码

    转自:http://developer.51cto.com/art/201003/190206.htm Java Socket通信读取有不少需要我们注意的知识点.当我们在使用的时候有很多的问题摆在我们 ...

随机推荐

  1. 基于visual Studio2013解决C语言竞赛题之1067间隔排序

        题目 解决代码及点评 /* 功能:间隔元素排序.用随机函数产生25个[25,75]之间的整数, 把它送到一维数组M中. 要求对M[I],M[I+J],M[I+2*J],-这些元 ...

  2. VC socket Connect 超时时间设置

    设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...

  3. boost::asio async_write也不能保证一次发完所有数据 二

    只有看boost源码才能弄明白发生了什么.首先我是将vector里面写入了数据,然后用boost::asio::buffer将vector构造成了mutable_buffer_1对象. 参考该文档的重 ...

  4. 重载new delete操作符是怎么调用的

    自定义的new操作符是怎么对英语new 一个对象的?自定义的delete操作符什么情况下得到调用?new一个对象时出现异常需要我操心内存泄露吗?下面的一个例子帮我们解开所有的疑惑. 1. 调用规则   ...

  5. Linux下搭建 Cocos2d-x-2.1.4 编译环境

    [tonyfield 2013.09.04 ] 参考 Linux下搭建 Cocos2d-x-2.1.4 编译环境 导入 HelloCpp 例程 1. Java 入口 HelloCpp.java Hel ...

  6. 正则表达式概述与JAVA中正则表达式的应用

    编程或者电脑使用过程中,经常需要对字符串进行 匹配,查找,替换,判断.如果单纯用代码 if () ,whlie 什么的进行比较复杂麻烦.正则表达式是一种强大灵活的文本处理工具,专门对字符串进行匹配,查 ...

  7. Ruby on Rails 實戰聖經阅读(二)

    1.操作系统 centos5.4 2.安装ruby yum install ruby 会安装得到 1.8.5 如果你公司用的是1.8.X就无所谓了, 拿这个学习就行了 如果你们公司用的是1.9.X,那 ...

  8. Oracle SQL语句执行过程

    前言 QQ群讨论的时候有人遇到这样的问题:where子句中无法访问Oracle自定义的字段别名.这篇 博客就是就这一问题做一个探讨,并发散下思维,谈谈SQL语句的执行顺序问题. 问题呈现 直接给出SQ ...

  9. alv 显示 汇总数据

    alv中有 字段设置 gs_fieldcat-do_sum = ‘1’.字段  用于控制汇总

  10. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...