• java_socket套接字网络编程


    ============================================================ 

                                              1.实现server和client模型程序

    ============================================================ 

    实现原理:

    ============================================================ 

    服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,

    在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),

    等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。  

    ============================================================ 
    客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,

    关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

    ============================================================ 

    服务器端代码:

    复制代码
     1 package com.b510.socket1703;
     2 
     3 import java.io.*;
     4 import java.net.Socket;
     5 import java.net.ServerSocket;
     6 
     7 /**
     8  * 服务器断的工作就是在指定的端口上监听
     9  * <li>建立连接</li>
    10  * <li>打开输出流</li>
    11  * <li>封装输出流</li>
    12  * <li>向客户端发送数据</li>
    13  * <li>关闭打开的输出流</li>
    14  * <li>关闭打开的socket对象</li>
    15  * 
    16  * @author Hongten
    17  * 
    18  * @time 2012-4-29  2012
    19  */
    20 public class TestServer {
    21     public static void main(String args[]) {
    22         try {
    23             // 指定服务器端的端口号为8888
    24             ServerSocket s = new ServerSocket(8888);
    25             while (true) {
    26                 // 建立连接
    27                 Socket socket = s.accept();
    28                 // 打开输出流
    29                 OutputStream os = socket.getOutputStream();
    30                 // 封装输出流
    31                 DataOutputStream dos = new DataOutputStream(os);
    32                 // s<li>.getInetAddress()获取远程ip地址,s<li>.getPort()远程客户端的断后好
    33                 // 向客户端发送数据
    34                 dos.writeUTF("你好,客户端地址信息: " + socket.getInetAddress()
    35                         + "\t客户端通信端口号: " + socket.getPort());
    36                 dos.writeUTF("i'm a server ,my name is hongten!");
    37                 // 关闭打开的输出流
    38                 dos.close();
    39                 // 关闭打开的socket对象
    40                 socket.close();
    41             }// 开始下一此循环
    42         } catch (IOException e) {
    43             e.printStackTrace();
    44         }
    45     }
    46 }
    复制代码

    客户端代码:

    复制代码
     1 package com.b510.socket1703;
     2 
     3 import java.io.*;
     4 import java.net.Socket;
     5 
     6 /**
     7  * 客户端
     8  * @author Hongten
     9  * 
    10  * @time 2012-4-29 2012
    11  */
    12 public class TestClient {
    13     public static void main(String args[]) {
    14         try {
    15             // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
    16             // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
    17             // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
    18             // refused: connect
    19             Socket s1 = new Socket("127.0.0.1", 8888);
    20             // 打开输入流
    21             InputStream is = s1.getInputStream();
    22             // 封装输入流
    23             DataInputStream dis = new DataInputStream(is);
    24             // 打印服务器端发送过来的信息
    25             System.out.println(dis.readUTF());
    26             System.out.println(dis.readUTF());
    27             // 关闭输入流
    28             dis.close();
    29             // 关闭打开的socket对象
    30             s1.close();
    31         } catch (IOException e) {
    32             e.printStackTrace();
    33         }
    34     }
    35 }
    复制代码

    如果服务器端没有打开,这时候运行客户端,出现的结果:

    复制代码
     1 java.net.ConnectException: Connection refused: connect
     2     at java.net.PlainSocketImpl.socketConnect(Native Method)
     3     at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
     4     at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
     5     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
     6     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
     7     at java.net.Socket.connect(Socket.java:518)
     8     at java.net.Socket.connect(Socket.java:468)
     9     at java.net.Socket.<init>(Socket.java:365)
    10     at java.net.Socket.<init>(Socket.java:179)
    11     at com.b510.socket1703.TestClient.main(TestClient.java:19)
    复制代码

    如果服务器端先打开服务,这时候客户端连接服务器端,出现的效果:

    1 你好,客户端地址信息: /127.0.0.1    客户端通信端口号: 2800
    2 i'm a server ,my name is hongten!

    ============================================================ 

                                                  2.实现单线程的聊天室

    ============================================================ 

    服务器端代码:

    复制代码
     1 package com.b510.socket1704.simplechatroom;
     2 
     3 import java.io.*;
     4 import java.net.Socket;
     5 import java.net.ServerSocket;
     6 import java.net.SocketException;
     7 
     8 /**
     9  * 服务器端程序,在while循环中所执行的动作是:
    10  * 听,说,听,说,听,说...
    11  * 
    12  * @author Hongten
    13  * 
    14  * @time 2012-4-29 2012
    15  */
    16 public class TestServer {
    17     public static void main(String args[]) {
    18         try {
    19             //创建一个socket对象
    20             ServerSocket s = new ServerSocket(8888);
    21             //socket对象调用accept方法,等待连接请求
    22             Socket s1 = s.accept();
    23             //打开输出流
    24             OutputStream os = s1.getOutputStream();
    25             //封装输出流
    26             DataOutputStream dos = new DataOutputStream(os);
    27             //打开输入流
    28             InputStream is = s1.getInputStream();
    29             //封装输入流
    30             DataInputStream dis = new DataInputStream(is);
    31             //读取键盘输入流
    32             InputStreamReader isr = new InputStreamReader(System.in);
    33             //封装键盘输入流
    34             BufferedReader br = new BufferedReader(isr);
    35 
    36             String info;
    37             while (true) {
    38                 //接受客户端发送过来的信息
    39                 info = dis.readUTF();
    40                 //打印接受的信息
    41                 System.out.println("对方说: " + info);
    42                 //如果发现接受的信息为:bye,那么就结束对话
    43                 if (info.equals("bye"))
    44                     break;
    45                 //读取键盘的输入流
    46                 info = br.readLine();
    47                 //写入到网络连接的另一边,即客户端
    48                 dos.writeUTF(info);
    49                 //如果服务器自己说:bye,也是结束对话
    50                 if (info.equals("bye"))
    51                     break;
    52             }
    53             //关闭输入流
    54             dis.close();
    55             //关闭输出流
    56             dos.close();
    57             //关闭socket对象
    58             s1.close();
    59             s.close();
    60         } catch (SocketException e) {
    61             System.out.println("网络连接异常,程序退出!");
    62         } catch (IOException e) {
    63             e.printStackTrace();
    64         }
    65     }
    66 }
    复制代码

    客户端代码:

    复制代码
     1 package com.b510.socket1704.simplechatroom;
     2 
     3 import java.io.*;
     4 import java.net.Socket;
     5 import java.net.SocketException;
     6 /**
     7  * 客户端程序,在while循环中所执行的动作是:
     8  * 说,听,说,听,说,听....
     9  * @author Hongten
    10  *
    11  * @time 2012-4-29  2012
    12  */
    13 public class TestClient {
    14     public static void main(String args[]) {
    15         try {
    16             // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
    17             // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
    18             // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
    19             // refused: connect
    20             Socket s1 = new Socket("localhost", 8888);
    21             //打开输出流
    22             OutputStream os = s1.getOutputStream();
    23             //封装输出流
    24             DataOutputStream dos = new DataOutputStream(os);
    25             //打开输入流
    26             InputStream is = s1.getInputStream();
    27             //封装输入流
    28             DataInputStream dis = new DataInputStream(is);
    29             //读取键盘输入流
    30             InputStreamReader isr = new InputStreamReader(System.in);
    31             //封装键盘输入流
    32             BufferedReader br = new BufferedReader(isr);
    33 
    34             String info;
    35             while (true) {
    36                 //客户端先读取键盘输入信息
    37                 info = br.readLine();
    38                 //把他写入到服务器方
    39                 dos.writeUTF(info);
    40                 //如果客户端自己说:bye,即结束对话
    41                 if (info.equals("bye"))
    42                     break;
    43                 //接受服务器端信息
    44                 info = dis.readUTF();
    45                 //打印
    46                 System.out.println("对方说: " + info);
    47                 if (info.equals("bye"))
    48                     break;
    49             }
    50             //关闭相应的输入流,输出流,socket对象
    51             dis.close();
    52             dos.close();
    53             s1.close();
    54         } catch (IOException e) {
    55             e.printStackTrace();
    56         }
    57     }
    58 }
    复制代码

    运行效果:

    服务器端效果>>>

    复制代码
    1 对方说: hell
    2 你好
    3 对方说: 嘿嘿
    4 你今天
    5 对方说: 13
    6 代售点
    复制代码

    客户端端效果>>>

    复制代码
    1 hell
    2 对方说: 你好
    3 嘿嘿
    4 对方说: 你今�?
    5 13
    6 对方说: 代售�?
    复制代码

    当前的程序不管是服务器端,还是客户端,都是单线程的。如: 服务器端说:"你好"

    1 //读取键盘的输入流
    2 info = br.readLine();
    3 //写入到网络连接的另一边,即客户端
    4 dos.writeUTF(info);
    5 //如果服务器自己说:bye,也是结束对话

    通过上面的代码,把"你好"发送出去了,这时候,程序又开始循环,运行到:

    1 //接受客户端发送过来的信息
    2 info = dis.readUTF();

    这段代码,其实在这里就阻塞在这里了。要等到客户端那边说了话,"嘿嘿",这时候这里的
    阻塞才会变为非阻塞状态,然后又继续说,说完后又继续阻塞......

    而对于客户端来说,其实是一样的道理,客户端说完"hello"后,进入:

    1 //接受服务器端信息
    2 info = dis.readUTF();

    到收听服务器端的信息,在这里也产生了阻塞,只有服务器端说了"你好",这个阻塞才变为非阻塞
    状态。然后又继续接下来的动作....

    ============================================================ 

                                                  3.实现多线程的聊天室

    ============================================================ 

    服务器端代码:

    复制代码
     1 package com.b510.socket1705.freeechatroom;
     2 
     3 import java.io.*;
     4 import java.net.*;
     5 
     6 /**
     7  * 服务器端程序
     8  * 
     9  * @author Hongten
    10  * 
    11  * @time 2012-4-29 2012
    12  */
    13 public class TestServer {
    14     public static void main(String args[]) {
    15         try {
    16             // 创建一个socket对象
    17             ServerSocket s = new ServerSocket(8888);
    18             // socket对象调用accept方法,等待连接请求
    19             Socket s1 = s.accept();
    20 
    21             // =========服务器端,在这里应该先打开输出流,在打开输入流,
    22             // =========因为服务器端执行的操作是先听,再说,听,说,听,说.....
    23 
    24             // 打开输出流
    25             OutputStream os = s1.getOutputStream();
    26             // 封装输出流
    27             DataOutputStream dos = new DataOutputStream(os);
    28             // 打开输入流
    29             InputStream is = s1.getInputStream();
    30             // 封装输入流
    31             DataInputStream dis = new DataInputStream(is);
    32             // 创建并启用两个线程
    33             new MyServerReader(dis).start();
    34             new MyServerWriter(dos).start();
    35         } catch (IOException e) {
    36             e.printStackTrace();
    37         }
    38     }
    39 }
    40 
    41 // 接受并打印客户端传过来的信息
    42 class MyServerReader extends Thread {
    43     private DataInputStream dis;
    44 
    45     public MyServerReader(DataInputStream dis) {
    46         this.dis = dis;
    47     }
    48 
    49     public void run() {
    50         String info;
    51         try {
    52             while (true) {
    53                 // 如果对方,即客户端没有说话,那么就会阻塞到这里,
    54                 // 这里的阻塞并不会影响到其他线程
    55                 info = dis.readUTF();
    56                 // 如果状态有阻塞变为非阻塞,那么就打印接受到的信息
    57                 System.out.println("对方说: " + info);
    58                 if (info.equals("bye")) {
    59                     System.out.println("对方下线,程序退出!");
    60                     System.exit(0);
    61                 }
    62             }
    63         } catch (IOException e) {
    64             e.printStackTrace();
    65         }
    66     }
    67 }
    68 
    69 // 从键盘获得输入流并写入信息到客户端
    70 class MyServerWriter extends Thread {
    71     private DataOutputStream dos;
    72 
    73     public MyServerWriter(DataOutputStream dos) {
    74         this.dos = dos;
    75     }
    76 
    77     public void run() {
    78         // 读取键盘输入流
    79         InputStreamReader isr = new InputStreamReader(System.in);
    80         // 封装键盘输入流
    81         BufferedReader br = new BufferedReader(isr);
    82         String info;
    83         try {
    84             while (true) {
    85                 info = br.readLine();
    86                 dos.writeUTF(info);
    87                 if (info.equals("bye")) {
    88                     System.out.println("自己下线,程序退出!");
    89                     System.exit(0);
    90                 }
    91             }
    92         } catch (IOException e) {
    93             e.printStackTrace();
    94         }
    95     }
    96 }
    复制代码

    客户端代码:

    复制代码
     1 package com.b510.socket1705.freeechatroom;
     2 
     3 import java.io.*;
     4 import java.net.*;
     5 
     6 /**
     7  * 客户端程序
     8  * 
     9  * @author Hongten
    10  * 
    11  * @time 2012-4-29 2012
    12  */
    13 public class TestClient {
    14     public static void main(String args[]) {
    15         try {
    16             // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
    17             // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
    18             // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
    19             // refused: connect
    20             Socket s1 = new Socket("127.0.0.1", 8888);
    21 
    22             // =========客户端,在这里应该先打开输入流,在打开输出流,
    23             // =========因为客户端执行的操作是先说,再听,说,听,说,听.....
    24 
    25             // 打开输入流
    26             InputStream is = s1.getInputStream();
    27             // 封装输入流
    28             DataInputStream dis = new DataInputStream(is);
    29             // 打开输出流
    30             OutputStream os = s1.getOutputStream();
    31             // 封装输出流
    32             DataOutputStream dos = new DataOutputStream(os);
    33 
    34             // 创建并启用两个线程
    35             new MyClientReader(dis).start();
    36             new MyClientWriter(dos).start();
    37         } catch (IOException e) {
    38             e.printStackTrace();
    39         }
    40     }
    41 }
    42 
    43 // 接受并打印服务器端传过来的信息
    44 class MyClientReader extends Thread {
    45     private DataInputStream dis;
    46 
    47     public MyClientReader(DataInputStream dis) {
    48         this.dis = dis;
    49     }
    50 
    51     public void run() {
    52         String info;
    53         try {
    54             while (true) {
    55                 info = dis.readUTF();
    56                 System.out.println("对方说: " + info);
    57                 if (info.equals("bye")) {
    58                     System.out.println("对方下线,程序退出!");
    59                     System.exit(0);
    60                 }
    61             }
    62         } catch (IOException e) {
    63             e.printStackTrace();
    64         }
    65     }
    66 }
    67 
    68 // 从键盘获得输入流并写入信息到服务器端
    69 class MyClientWriter extends Thread {
    70     private DataOutputStream dos;
    71 
    72     public MyClientWriter(DataOutputStream dos) {
    73         this.dos = dos;
    74     }
    75 
    76     public void run() {
    77         InputStreamReader isr = new InputStreamReader(System.in);
    78         BufferedReader br = new BufferedReader(isr);
    79         String info;
    80         try {
    81             while (true) {
    82                 info = br.readLine();
    83                 dos.writeUTF(info);
    84                 if (info.equals("bye")) {
    85                     System.out.println("自己下线,程序退出!");
    86                     System.exit(0);
    87                 }
    88             }
    89         } catch (IOException e) {
    90             e.printStackTrace();
    91         }
    92     }
    93 }
    复制代码

    客户端运行效果:

    1 这是客户端
    2 我是hongten
    3 这是我说的第三句话,haha
    4 对方说: 我是服务器端,这说我说的第一句话,hehe

    服务器端运行效果:

    1 对方说: 这是客户�?
    2 对方说: 我是hongten
    3 对方说: 这是我说的第三句话,haha
    4 我是服务器端,这说我说的第一句话,hehe
  • 相关阅读:
    spring aop实现过程之三Spring AOP中Aspect编织的实现
    spring aop实现过程之一代理对象的生成
    数据库常用面试题(SQL Server) (转载)
    回溯法解八后问题
    masmplus增加调试工具
    c++ new关键字 详解
    EMU8086 编译器使用简介
    汇编操作显存
    回溯法简介
    汇编链接时 错误:unresolved external symbol _WinMainCRTStartup
  • 原文地址:https://www.cnblogs.com/zyn1990/p/4024829.html
Copyright © 2020-2023  润新知