Socket实例,实现多个客户端连接同一个服务端代码&TCP网络编程 ServerSocket和Socket实现多客户端聊天

这篇具有很好参考价值的文章主要介绍了Socket实例,实现多个客户端连接同一个服务端代码&TCP网络编程 ServerSocket和Socket实现多客户端聊天。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java编程Socket实现多个客户端连接同一个服务端代码

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

使用socket实现多个客户端和同一客户端通讯;首先客户端连接服务端发送一条消息,服务端接收到消息后进行处理,完成后再回复客户端一条消息。

服务端代码

public class server {
  
    public static void main(string[] args) throws ioexception {
        // 为了简单起见,所有的异常信息都往外抛
        int port = 8899;
        // 定义一个servicesocket监听在端口8899上
        serversocket server = new serversocket(port);
        system.out.println("等待与客户端建立连接...");
        while (true) {
            // server尝试接收其他socket的连接请求,server的accept方法是阻塞式的
            socket socket = server.accept();
            /**
       * 我们的服务端处理客户端的连接请求是同步进行的, 每次接收到来自客户端的连接请求后,
       * 都要先跟当前的客户端通信完之后才能再处理下一个连接请求。 这在并发比较多的情况下会严重影响程序的性能,
       * 为此,我们可以把它改为如下这种异步处理与客户端通信的方式
       */
            // 每接收到一个socket就建立一个新的线程来处理它
            new thread(new task(socket)).start();
        }
        // server.close();
    }
    /**
   * 处理socket请求的线程类
   */
    static class task implements runnable {
        private socket socket;
        /**
     * 构造函数
     */
        public task(socket socket) {
            this.socket = socket;
        }
        @override
            public void run() {
            try {
                handlersocket();
            }
            catch (exception e) {
                e.printstacktrace();
            }
        }
        /**
     * 跟客户端socket进行通信
     *
     * @throws ioexception
     */
        private void handlersocket() throws exception {
            // 跟客户端建立好连接之后,我们就可以获取socket的inputstream,并从中读取客户端发过来的信息了
            /**
       * 在从socket的inputstream中接收数据时,像上面那样一点点的读就太复杂了,
       * 有时候我们就会换成使用bufferedreader来一次读一行
       *
       * bufferedreader的readline方法是一次读一行的,这个方法是阻塞的,直到它读到了一行数据为止程序才会继续往下执行,
       * 那么readline什么时候才会读到一行呢?直到程序遇到了换行符或者是对应流的结束符readline方法才会认为读到了一行,
       * 才会结束其阻塞,让程序继续往下执行。
       * 所以我们在使用bufferedreader的readline读取数据的时候一定要记得在对应的输出流里面一定要写入换行符(
       * 流结束之后会自动标记为结束,readline可以识别),写入换行符之后一定记得如果输出流不是马上关闭的情况下记得flush一下,
       * 这样数据才会真正的从缓冲区里面写入。
       */
            bufferedreader br = new bufferedreader(
                      new inputstreamreader(socket.getinputstream(), "utf-8"));
            stringbuilder sb = new stringbuilder();
            string temp;
            int index;
            while ((temp = br.readline()) != null) {
                if ((index = temp.indexof("eof")) != -1) {
                    // 遇到eof时就结束接收
                    sb.append(temp.substring(0, index));
                    break;
                }
                sb.append(temp);
            }
            system.out.println("form cliect[port:" + socket.getport()
                      + "] 消息内容:" + sb.tostring());
            // 回应一下客户端
            writer writer = new outputstreamwriter(socket.getoutputstream(),
                      "utf-8");
            writer.write(string.format("hi,%d.天朗气清,惠风和畅!", socket.getport()));
            writer.flush();
            writer.close();
            system.out.println(
                      "to cliect[port:" + socket.getport() + "] 回复客户端的消息发送成功");
            br.close();
            socket.close();
        }
    }
}

客户端代码

import java.io.inputstreamreader;
import java.io.outputstreamwriter;
import java.io.reader;
import java.io.writer;
import java.net.socket;
/** * socket客户端
* 功能说明: * * @author 大智若愚的小懂 * @date 2016年8月30日 * @version 1.0 */
public class client {
    /** * 入口 * @param args */
    public static void main(string[] args) {
        // 开启三个客户端,一个线程代表一个客户端
        for (int i = 0; i < 3; i++) {
            new thread(new runnable() {
                @override public void run() {
                    try {
                        testclient client = testclientfactory.createclient();
                        client.send(string.format("hello,server!i'm %d.这周末天气如何。", client.client.getlocalport()));
                        client.receive();
                    }
                    catch (exception e) {
                        e.printstacktrace();
                    }
                }
            }
            ).start();
        }
    }
    /** * 生产测试客户端的工厂 */
    static class testclientfactory {
        public static testclient createclient() throws exception {
            return new testclient("127.0.0.1", 8899);
        }
    }
    /** * 测试客户端 */
    static class testclient {
        /** * 构造函数 * @param host 要连接的服务端ip地址 * @param port 要连接的服务端对应的监听端口 * @throws exception */
        public testclient(string host, int port) throws exception {
            // 与服务端建立连接
            this.client = new socket(host, port);
            system.out.println("cliect[port:" + client.getlocalport() + "] 与服务端建立连接...");
        }
        private socket client;
        private writer writer;
        /** * 发送消息 * @param msg * @throws exception */
        public void send(string msg) throws exception {
            // 建立连接后就可以往服务端写数据了
            if(writer == null) {
                writer = new outputstreamwriter(client.getoutputstream(), "utf-8");
            }
            writer.write(msg);
            writer.write("eof\n");
            writer.flush();
            // 写完后要记得flush
            system.out.println("cliect[port:" + client.getlocalport() + "] 消息发送成功");
        }
        /** * 接收消息 * @throws exception */
        public void receive() throws exception {
            // 写完以后进行读操作
            reader reader = new inputstreamreader(client.getinputstream(), "utf-8");
            // 设置接收数据超时间为10秒
            client.setsotimeout(10*1000);
            char[] chars = new char[64];
            int len;
            stringbuilder sb = new stringbuilder();
            while ((len = reader.read(chars)) != -1) {
                sb.append(new string(chars, 0, len));
            }
            system.out.println("cliect[port:" + client.getlocalport() + "] 消息收到了,内容:" + sb.tostring());
            reader.close();
            // 关闭连接
            writer.close();
            client.close();
        }
    }
}

接下来模拟一下:

1.首先运行服务端

socket多个客户端与一个服务器,Java细节,网络,Java,Socket

2.接着运行客户端(开三个客户端请求)

为了演示有所区分,服务端我使用的是eclipse工具,客户端使用的是intellij idea工具。这时可以看到客户端在控制台打印出来的消息

socket多个客户端与一个服务器,Java细节,网络,Java,Socket

一个port端口号代表一个客户端,回过来看下服务端在控制台打印出来的消息

socket多个客户端与一个服务器,Java细节,网络,Java,Socket



TCP网络编程 ServerSocket和Socket实现多客户端聊天

目标

使用SeverSocket 和 Socket 实现双人、多人聊天

过程分析

思路

大致说一下,整体思路
1.实现一个群发效果,且需要执行判断,当前的客户端发送的信息,并不需要通过Server端发送给自己。
2.实现循环侦听,因为有多个套接字请求,所以需要将它们“存起来”。
3.根据循环侦听结果创建多个线程,每条线程都是平级关系,每条线程需要实现发送功能,读取功能(将读取到的信息发送出去)

详细分析

1.每条线程需要单独运行一遍,才能实现群发效果
2.每条线程内的:发送方法、run方法、读取方法 都是不同的socket
3.将每一条线程存到集合,使用当前的线程调取群发方法时,遍历判断,然后切换到其他线程进行发送操作。
4.大概就是:循环(侦听、创建新线程)——存储线程——当前线程接收信息——发送信息——调取群发——切换线程完成发送
5.服务器只有及时转发,和循环监听
socket多个客户端与一个服务器,Java细节,网络,Java,Socket

代码示例

Server端

首先要侦听所有的套接字,侦听到一个,就启动一个线程,并将其存至集合
子线程写了发送方法,run方法,接收方法
还有一个单例,需要保证该群发类只有一个实例对象

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Vector;
/*服务器端:一个线程专门发送和接收消息  一个线程监听所有Socket。
 客户端:一个线程专门发送消息,一个线程专门接收消息。*/
public class QunLiaoServer {
    public static void main(String[] args) throws IOException {
        ServerAccept sa = new ServerAccept();
        sa.start();
    }
}
//创建侦听类
class ServerAccept extends Thread{
    @Override
    public void run() {
        try {
            System.out.println("等待客户端连接");
            ServerSocket ss = new ServerSocket(35555);
    //由于可能当有多个客户端连接时,accept方法就会产生多个Socket对象,需加一个while循环监听来自客户端的连接            
            while(true){
                //侦听套接字的连接,accept是一个阻塞的方法,会阻塞当前的线程
                Socket s = ss.accept();
                //建立连接,表示serverSocket在监听,如果监听到有客户端连接则会调用accept方法,然后返回一个Socket,最后建立连接
                System.out.println("连接成功"+s.getPort());
                //传递当前连接的客户端套接字
                SocketShouFa rs = new SocketShouFa(s);//会产生多条线程
                rs.start();
                //传递该线程
                QunFa.getQunFa().add(rs,s);//只有一个实例
                //当第一个socket被侦听到,且被传递下去,会死循环侦听下一个socket,并传递下去
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
//创建接收和发送类线程 (客户端信息接收,发送方法)
 class SocketShouFa extends Thread{
    Socket socket;
    public SocketShouFa (Socket s){
        this.socket=s;
    }
    public void firstSend(String str,Socket nowsocket){
        try {
            socket.getOutputStream().write((Thread.currentThread().getName()+"端口:"+nowsocket.getPort()+"-->发送:"+str+"\r\n").getBytes());
        } catch (IOException e) {
             System.out.println("断开了客户端,没有客户端接收信息");//当前接收的客户端断开,无法写给客户端信息会报错
            e.printStackTrace();
            //需要写一个清除当前该客户端的方法
            QunFa.getQunFa().remove(this,socket);
        }    
    }
    //重写run方法
    //线程执行至此,需要接收客户端的信息
    @Override
    public void run() {
        firstSend("您已经连接到服务器",socket);
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line=null;
            //接收客户端的数据
            while ((line=br.readLine())!=null) {
            //然后服务器再将所有的信息转发给每一个客户端,调用qunFa方法 
              QunFa.getQunFa().qunFa(this, line);
   }
        } catch (IOException e) {
             System.out.println(Thread.currentThread().getName()+"客户端已断开");
            e.printStackTrace();
        }
    }
}
//创建群发类(创建单例模型;集合存储 SocketShouFa线程 和套接字 ;实现群发,调取发送方法)
class QunFa{
    //创建单例模型
    private QunFa(){
    }
    private static final QunFa si= new QunFa();
    public static QunFa getQunFa(){
        return si;
    }
    //创建一个存储 线程 和端口  的Hashtable集合
    Hashtable<SocketShouFa,Socket> ht = new Hashtable<SocketShouFa,Socket>();
     public void add(SocketShouFa ri,Socket nowsocket){
         //将每一个线程 和 对应的socket 加入集合中
         ht.put(ri, nowsocket);
     }
     //线程清除
     public void remove(SocketShouFa ri,Socket nowsocket) {
          ht.remove(ri, nowsocket);
     }
    //表示当前的线程给集合中的 非自己 的线程发送的信息
     public void qunFa(SocketShouFa ri,String img){
         //遍历集合
         for (Entry<SocketShouFa, Socket> entry : ht.entrySet()) {
             SocketShouFa nowRi = entry.getKey();
                 //如果遍历线程 和 当前线程不一致,就进入
                if(!ri.equals(nowRi)){
                    //传递 不一致客户端线程,并且发送当前 线程的socket信息
                    nowRi.firstSend(img, ht.get(ri));
                }
            }
     }
}

Client端

这里有两个线程被启用了,一个是主线程去读取信息,一个子线程发送信息

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ClientB {
    public static void main(String[] args) {
        // 创建客户端对象
        try {
            Socket s = new Socket("192.168.0.243", 35555);
            SendImgClientB sendclient = new SendImgClientB(s);
            sendclient.start();
            // 创建读取字符流
            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            while(true){
                //读取服务端发过来的信息
                String serverimg = br.readLine();
                System.out.println(serverimg);
            }
        } catch (IOException e) {
            System.out.println("服务器下线了");
            e.printStackTrace();
        }
    }
}
class SendImgClientB extends Thread {
    Socket ss;
    PrintWriter pw;
    Scanner sc =new Scanner(System.in);
    public SendImgClientB(Socket s) {
        this.ss = s;
        try {
            this.pw = new PrintWriter(s.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        try {
            while (true) {
                // 客户端发送信息
                String in = sc.next();
                pw.println(in);
                pw.flush();// 输出流刷新
                if (in.equals("end")) {
                    break;
                }
            }
        } catch (Exception e) {
            System.out.println("服务器下线了");
            e.printStackTrace();
        } finally {
            if (pw != null) {
                pw.close();
            }
            if (ss != null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果

socket多个客户端与一个服务器,Java细节,网络,Java,Socket文章来源地址https://www.toymoban.com/news/detail-533318.html

到了这里,关于Socket实例,实现多个客户端连接同一个服务端代码&TCP网络编程 ServerSocket和Socket实现多客户端聊天的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java socket Server TCP服务端向指定客户端发送消息;可查看、断开指定连接的客户端;以及设置客户端最大可连接数量。

    首先需要知道java里如何创建一个Socket服务器端。 提示:注意server.accept()方法调用会阻塞,只有新的客户端连接后才返回一个新的socket对象。如果一直未连接那么会一直处于阻塞状态 了解了如何创建一个socket服务器端后。那么如何实现给指定的连接客户端发送消息呢?首先我

    2024年02月11日
    浏览(73)
  • C# socket——简单的TCP 客户端 连接通信

    TCP编程的客户端一般步骤是: 1、创建一个socket,用函数socket()。 2、设置socket属性。 3、设置要连接的对方的IP地址和端口等属性。 4、连接服务器,用函数connect()。 5、收发数据,用函数send()和recv(),或者read()和write()。 6、关闭网络连接。 using System; using System.Net; using System.

    2024年02月11日
    浏览(52)
  • python socket监测服务器和客户端连接状态

    服务器端和客户端的连接状态,应该是没有单独的函数返回或是接口监测的,看网上很多资料说需要监测心跳,这确实是一个普遍解决监测状态的办法,但是对我的项目却显得有些被动,其实对一般的项目包括我的,用try…except就可以满足,里面设置标志位,if判断一下就可

    2024年02月13日
    浏览(43)
  • tcp服务器端与多个客户端连接

    如果希望Tcp服务器端可以与多个客户端连接,可以这样写: 相关的槽函数中: 使用sender()来获取对应的QTcpSocket对象。 其实,主要就是QTcpServer进行监听: 客户端的QTcpSocket与服务器端的QTcpSocket进行通信。

    2024年04月28日
    浏览(39)
  • Linux下网络编程(3)——socket编程实战,如何构建一个服务器和客户端连接

            经过前几篇的介绍,本文我们将进行编程实战,实现一个简单地服务器和客户端应用程序。 编写服务器程序          编写服务器应用程序的流程如下:         ①、调用 socket()函数打开套接字,得到套接字描述符;         ②、调用 bind()函数将套接字

    2024年02月03日
    浏览(67)
  • FRP 进行内网穿透,在一台客户端上配置多台服务器连接,winsw 配置多个 windows 自启动服务,Windows 远程桌面连接时目标客户端断开 WIFI连接解决办法

    本篇博客建立在已经使用 FRP 实现通过一台服务器范围一台客户端的基础上,不会从头开始对如何配置 FRP 实现内网穿透进行介绍。有需要这方面的同学可以参考下面这篇文章:【计算机网络相关】内网穿透介绍以及使用FRP实现内网穿透Windows远程桌面_frp内网穿透-CSDN博客 本篇

    2024年02月01日
    浏览(69)
  • Tcp server是如何一个端口处理多个客户端连接的(一对一还是一对多)

    我们经常看到说,TCP 是一对一的两点服务,UDP 支持一对一、一对多、多对多的交互通信。但是使用Tcp工具通讯时,一个Tcp服务端可以连接多个Tcp客户端。所以这里的一对一和一对多是不是冲突了? 并不是 。一对一指的是Tcp连接,什么是Tcp连接,这里直接粘贴小林大神的解释

    2023年04月08日
    浏览(49)
  • 因项目只做socket客户端,不想用workerman或者swoole框架,简单实现ws PHP客户端

    docs/Client.md · master · mirrors / Textalk / websocket-php · GitCode

    2024年02月13日
    浏览(63)
  • 使用socket.io简单实现多客户端可编辑表格

    之前看了B站小野森森老师的可编辑表格的视频深受启发,今天使用React简单实现一下。 当处于编辑状态的时候,自己和其他人可以看到; 编辑内容后,自己及其他人可以同步看到修改后的内容; 后端服务,使用socket.io起一个后端服务,用于监听连接和发送数据; 前端准备:

    2024年02月06日
    浏览(49)
  • 基于C# Socket实现的简单的Redis客户端

         Redis 是一款强大的高性能键值存储数据库,也是目前 NOSQL 中 最流行 比较流行的一款数据库,它在广泛的应用场景中扮演着至关重要的角色,包括但不限于缓存、消息队列、会话存储等。在本文中,我们将介绍如何基于 C# Socket 来实现一个简单的Redis客户端类 RedisClien

    2024年02月05日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包