Socket和ServerSocket

Socket以及ServerSocket所涉及的异常类型
以下四种类型都是继承于IOException,所以很多之后直接弹出IOException
UnkownHostException:  主机名字或IP错误
ConnectException:    服务器拒绝连接、服务器没有启动、(超出队列数,拒绝连接)
SocketTimeoutException: 连接超时
BindException:      Socket对象无法与制定的本地IP地址或端口绑定

交互过程

Socket与ServerSocket的交互

Socket与ServerSocket的交互.jpg

Socket编程Server端5步
1、启动ServerSocket ServerSocket serverSocket=new ServerSocket(post);
2、侦听连接:Socket socket=serverSocket.accept();
3、读取数据:BuffereRead input = new BufferedReader(new InputStreamReader(socket.getInputStream());
String s =intput.readLine();
4、写数据:BuffereWrite input = new BufferedWrite(new OutputStreamWrite(socket.getOutputStream());
intput.write(s,0,s.length());
5、关闭连接:socket.close();
serverSocket.close();

Client端4步
1、启动Server Socket socket = new Socket("localhost",post);
2、读取数据:BuffereRead input = new BufferedReader(new InputStreamReader(socket.getInputStream());
String s =intput.readLine();
3、写数据:BuffereWrite input = new BufferedWrite(new OutputStreamWrite(socket.getOutputStream());
intput.write(s,0,s.length());
4、关闭连接:socket.close();

Socket构造函数
Socket()
Socket(InetAddress address, int port)throws UnknownHostException, IOException
Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException
Socket(String host, int port)throws UnknownHostException, IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException
除去第一种不带参数的之外,其它构造函数会尝试建立与服务器的连接。如果失败会抛出IOException错误。如果成功,则返回Socket对象。
InetAddress是一个用于记录主机的类,其静态getHostByName(String msg)可以返回一个实例,其静态方法getLocalHost()也可以获得当前主机的IP地址,并返回一个实例。Socket(String host, int port, InetAddress localAddress, int localPort)构造函数的参数分别为目标IP、目标端口、绑定本地IP、绑定本地端口。

Socket方法
getInetAddress();   远程服务端的IP地址
getPort();       远程服务端的端口
getLocalAddress()   本地客户端的IP地址
getLocalPort()     本地客户端的端口
getInputStream();  获得输入流
getOutStream();   获得输出流

Socket状态
isClosed();     //连接是否已关闭,若关闭,返回true;否则返回false
isConnect();      //如果曾经连接过,返回true;否则返回false
isBound();     //如果Socket已经与本地一个端口绑定,返回true;否则返回false
如果要确认Socket的状态是否处于连接中,下面语句是很好的判断方式。
boolean isConnection=socket.isConnected() && !socket.isClosed(); //判断当前是否处于连接

ServerSocket构造函数
ServerSocket()throws IOException
ServerSocket(int port)throws IOException
ServerSocket(int port, int backlog)throws IOException
ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException
注意:

  1. port服务端要监听的端口;backlog客户端连接请求的队列长度;bindAddr服务端绑定IP
  2. 如果端口被占用或者没有权限使用某些端口会抛出BindException错误。譬如1~1023的端口需要管理员才拥有权限绑定。
  3. 如果设置端口为0,则系统会自动为其分配一个端口;
  4. bindAddr用于绑定服务器IP,为什么会有这样的设置呢,譬如有些机器有多个网卡。
  5. ServerSocket一旦绑定了监听端口,就无法更改。ServerSocket()可以实现在绑定端口前设置其他的参数。

多线程的ServerSocket实现方式:
主线程会循环执行ServerSocket.accept();
当拿到客户端连接请求的时候,就会将Socket对象传递给多线程,让多线程去执行具体的操作;
实现多线程的方法要么继承Thread类,要么实现Runnable接口。当然也可以使用线程池,但实现的本质都是差不多的。
下面代码为服务器的主线程。为每个客户分配一个工作线程:

try {
    System.out.println("正在启动服务。。。。");
    ServerSocket serverSocket = new ServerSocket(6666);
    while(true){
        Socket socket = serverSocket.accept();
        System.out.println("连接客户端");
        InputThread inputThread = new InputThread(socket);
        inputThread.start();
    }
} catch (IOException e) {
    e.printStackTrace();
}

使 InputThread继承自Thread类,并实现InputStram和OutputStram

public class InputThread extends Thread{

    Socket socket;
    BufferedReader input;
    BufferedWriter output;

    public InputThread(Socket socket){
        this.socket = socket;
        try {
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void run(){
        boolean shouldContinue=true;
        while(shouldContinue){
            try {
                String msg = this.input.readLine();
                System.out.println("client:" + msg);
                
                if("bye".equals(msg)) break;
                
                Random random = new Random();
                int luckNum = random.nextInt(100);
                System.out.println("luckNum" + luckNum);
                this.output.write(luckNum + "\r");
                this.output.flush();
                
            } catch (IOException e) {
                e.printStackTrace();
            }   
        }
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容