java模拟多线程socket通信

1.socket通信

Socket原理机制:
1.通信的两端都有Socket
2.网络通信其实就是Socket间的通信
3.数据在两个Socket间通过IO传输

socket和serverSocket通信简单介绍如下,注意客户端与服务器端是怎么交换数据的:


应用多线程实现服务器与多客户端之间的通信:

① 服务器端创建ServerSocket,循环调用accept()等待客户端连接
② 客户端创建一个socket并请求和服务器端连接
③ 服务器端接受请求,创建socket与该客户建立专线连接
④ 建立连接的两个socket在一个单独的线程上对话
⑤ 服务器端继续等待新的连接

2.服务器端代码

package com.tl.skyLine.socket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 聊天 服务器端
 * Created by tl on 17/3/1.
 */
public class ChatServer {
    private int port = 8080;// 默认服务器端口

    public ChatServer() {
    }

    // 创建指定端口的服务器
    public ChatServer(int port) {
        this.port = port;
    }

    // 提供服务
    public void service() {
        int i = 0;
        try {
            // 建立服务器连接,设定客户连接请求队列的长度
            ServerSocket server = new ServerSocket(port, 3);
            while (true) {
                // 等待客户连接
                Socket socket = server.accept();
                i++;
                System.out.println("第" + i + "个客户连接成功!");
                new Thread(new ServerThread(socket, i)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new ChatServer().service();
    }
}


class ServerThread implements Runnable {
    private int index;
    private Socket socket;

    public ServerThread(Socket socket, int i) {
        this.socket = socket;
        this.index = i;
    }

    // 任务是为一个用户提供服务
    @Override
    public void run() {
        try {
            try {
                // 读取客户端传过来信息的DataInputStream
                DataInputStream in = new DataInputStream(socket
                        .getInputStream());
                // 向客户端发送信息的DataOutputStream
                DataOutputStream out = new DataOutputStream(socket
                        .getOutputStream());
                while (true) {
                    // 读取来自客户端的信息
                    String accpet = in.readUTF();
                    System.out.println("第" + index + "个客户端发出消息:" + accpet);
                }
            } finally {// 建立连接失败的话不会执行socket.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.客户端代码

package com.tl.skyLine.socket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;

/**
 * 聊天 客户端
 * Created by tl on 17/3/1.
 */
public class ChatClient {
    private String host = "localhost";// 默认连接到本机
    private int port = 8080;// 默认连接到端口8080

    private String name = String.valueOf(new Random().nextInt(999999));//客户端的名字

    public ChatClient() {

    }

    // 连接到指定的主机和端口
    public ChatClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void chat() {
        try {
            // 连接到服务器
            Socket socket = new Socket(host, port);
            // 设置超时
//            Socket s = new Socket();
//            SocketAddress socketAddress = new InetSocketAddress(serverIp, port);
//            s.connect(socketAddress, timeout);
            try {
                // 读取服务器端传过来信息的DataInputStream
                DataInputStream in = new DataInputStream(socket
                        .getInputStream());
                // 向服务器端发送信息的DataOutputStream
                DataOutputStream out = new DataOutputStream(socket
                        .getOutputStream());

                // 装饰标准输入流,用于从控制台输入
                Scanner scanner = new Scanner(System.in);

                while (true) {
                    String send = scanner.nextLine();
                    // 把从控制台得到的信息传送给服务器
                    out.writeUTF("客户端[" + name + "]:" + send);
                    // 读取来自服务器的信息
                    String accpet = in.readUTF();
                    System.out.println(accpet);
                }

            } finally {
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new ChatClient().chat();
    }
}

以上代码利用Socket对象和ServerSocket对象进行简单的网络交互,即客户端通过DataOutputStream对象的writeUTF()方法向服务器发送消息,服务器利用DataInputStream对象的readUTF()方法读出数据。其中ServerSocket对象的accept()方法是阻塞的方法,它会一直等待,直到有客户端连接,同理,DataInputStream对象的readUTF()方法也是阻塞的方法,它也会一直等待,直到客户端调用writeUTF()方法。

上面代码中ChatClient.java中,客户端控制台发送信息之后,String accpet = in.readUTF();将会一直阻塞,如果是单线程的话,重新开一个客户端,也是处于阻塞当中,所以将服务端设置为多线程,这样就不会影响下一个客户端的通信。

4.运行结果:


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值