Java通过 Socket 实现 TCP服务端(一个实例)

1 Java Socket简介

  所谓socket 通常也称作”套接字“,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。Socket和ServerSocket类库位于Java.NET包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。

2 TCPServer代码实例

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TCP服务器端,单例模式
 * @author xiang
 *
 */
public class TCPServer implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(TCPServer.class);
    //成员变量/
    private static TCPServer serverInstance;
    private static Map<String, SocketThread> socketMaps = new HashMap<String,SocketThread>();        //每个客户端连接时都会新建一个SocketThread与之对应   private static ServerSocket serverSocket;                    //服务器套接字
    private static int serPort = 9999;                            //服务器端口号
    private static boolean flag;                                //服务器状态标志
    private static final int BUFFER_SIZE = 512;                    //数据接收字符数组大小

    //构造函数/
    private TCPServer() {

    }

    /**
     * 获取实例
     * @return TCPServer实例serverInstance
     */
    public static TCPServer getServerInstance(){
        if(serverInstance==null)
            serverInstance = new TCPServer();
        return serverInstance;
    }

    /**
     * 开启服务器
     * @throws IOException
     */
    public void openTCPServer() throws IOException{       if(serverSocket==null || serverSocket.isClosed()){
            serverSocket = new ServerSocket(serPort);
            flag = true;
        }
    }

    /**
     * 关闭服务器
     * @throws IOException
     */
    public void closeTCPServer() throws IOException{
        flag = false;      if(serverSocket!=null)
            serverSocket.close();
        /*for (Map.Entry<String, SocketThread> entry : socketMaps.entrySet()) {
             System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
        } */
        for (SocketThread value : socketMaps.values())
            value.closeConnect();
        socketMaps.clear();
    }

    /**
     * 服务器向客户端发送数据
     * @param bytes[]:待发送的字符数组
     * @param key 客户端的key,为空或""时表示数据群发
     * @throws IOException
     */
    public void sendMessage(String key,byte[] msgBytes){
        if(key==null||key.equals("")){
            for (SocketThread value : socketMaps.values())
                value.sendMassage(msgBytes);
        }else{
            SocketThread thread = socketMaps.get(key);
            if(thread!=null)
                thread.sendMassage(msgBytes);
        }
    }

    /**
     * 服务器向客户端发送数据
     * @param key 客户端的key,为空或""时表示数据群发
     * @param msgStr:待发送的字符串
     * @throws IOException
     */
    public void sendMessage(String key,String msgStr){      byte[] sendByte = msgStr.getBytes();
        if(key==null||key.equals("")){
            for (SocketThread value : socketMaps.values())
                value.sendMassage(sendByte);
        }else{
            SocketThread thread = socketMaps.get(key);
            if(thread!=null)
                thread.sendMassage(sendByte);
        }
    }

    @Override
    public void run() {
        logger.info("服务器线程已经启动");      while(true){
            try {
                while(flag){
                    logger.info("服务器线程在监听状态中");
                    Socket socket = serverSocket.accept();
                    String key = socket.getRemoteSocketAddress().toString();
                    SocketThread thread = new SocketThread(socket,key);
                    thread.start();
                    socketMaps.put(key, thread);
                    logger.info("有客户端连接:"+key);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }         

    /**
     * 处理连接后的数据接收请求内部类
     * @author xiang
     *
     */
    private class SocketThread extends Thread{
        private Socket socket;
        private String key;
        private OutputStream out;
        private InputStream in;

        //构造函数
        public SocketThread(Socket socket,String key) {
            this.socket = socket;
            this.key = key;
        }

        /**
         * 发送数据
         * @param bytes
         * @throws IOException
         */
        public void sendMassage(byte[] bytes){
            try {
                if(out==null)
                    out = socket.getOutputStream();
                out.write(bytes);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    closeConnect();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                socketMaps.remove(key);
            }
        }

        /**
         * 关闭连接,释放资源
         * @throws IOException
         */
        public void closeConnect() throws IOException{
            if(out!=null)    out.close();
            if(in!=null)    in.close();
            if(socket!=null && socket.isConnected())    socket.close();
        }

        @Override
        public void run() {
            byte[] receivBuf = new byte[BUFFER_SIZE];
            int recvMsgSize;
            try {
                in = socket.getInputStream();
                out = socket.getOutputStream();
                while ((recvMsgSize = in.read(receivBuf)) != -1) {
                    String receivedData = new String(receivBuf, 0, recvMsgSize);
                    System.out.println("Reverve form[port" + socket.getPort() + "]:" + receivedData);
                    System.out.println("Now the size of socketMaps is" + socketMaps.size());
                    /**************************************************************
                     *
                     * 接收数据后的处理过程
                     *
                     **************************************************************/
                }
                // response to client
                byte[] sendByte = "The Server has received".getBytes();
                // out.write(sendByte, 0, sendByte.length);
                out.write(sendByte);
                System.out.println("To Cliect[port:" + socket.getPort() + "] 回复客户端的消息发送成功");
                closeConnect();
                socketMaps.remove(key);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    closeConnect();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }

        //////////////
        public int getport(){
            return socket.getPort();
        }
    }
    //. end SocketThread
}
时间: 2024-10-15 02:50:46

Java通过 Socket 实现 TCP服务端(一个实例)的相关文章

Go语言中Socket通信TCP服务端

1.用法: (1)定义远程IP地址.使用net.ResolveTCPAddr()方法,定义一个TCP地址,做为本机监听地址. (2)使用net.ListenTCP("tcp",localAddress)方法开始监听,并返回tcpListener对像. (3)使用tcpListener.AcceptTCP方法进行接受连接.返回:net.TCPConn对像. (4)对net.TCPConn对像进行读写操作. (5)关闭连接. 2.代码: package main import ( &quo

Linux socket编程入门(1)-TCP服务端

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #define DEFAULT_PORT 8000 #define MAXLINE 4096 int main(int argc, char

tcp服务端socket

import socket if __name__ == '__main__': # 创建tcp服务端socket tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 立即释放端口号,重用端口 # SOL_SOCKET: 表示当前socket # SO_REUSEADDR: 是否立即释放端口选项 # True:表示立即释放端口 tcp_server_socket.setsockopt(socket.SOL

Python socket模块实现TCP服务端客户端

Python socket模块实现TCP服务端客户端 写了详细的注释,如果有哪一行不明白,可留言哦. 服务端脚本 # _*_ coding: utf-8 _*_ __author__ = 'xiaoke' __date__ = '2018/6/13 14:39' # 这个脚本创建一个TCP服务器,它接收来自客户端的消息,然后将消息加上时间戳前缀并返回客户端 import socket from time import ctime HOST = '' PORT = 21567 BUFSIZ = 4

手写一个模块化的 TCP 服务端客户端

前面的博客 基于 socket 手写一个 TCP 服务端及客户端 写过一个简单的 TCP 服务端客户端,没有对代码结构进行任何设计,仅仅是实现了相关功能,用于加深对 socket 编程的认识. 这次我们对整个代码结构进行一下优化,使其模块化,易扩展,成为一个简单意义上的“框架”. 对于 Socket 编程这类所需知识偏底层的情况(OS 协议栈的运作机制,TCP 协议的理解,多线程的理解,BIO/NIO 的理解,阻塞函数的运作原理甚至是更底层处理器的中断.网卡等外设与内核的交互.核心态与内核态的切

Java之Socket的TCP

//客户端发数据到服务端 * Tcp传输,客户端建立的过程. * 1,创建tcp客户端socket服务.使用的是Socket对象. * 建议该对象一创建就明确目的地.要连接的主机. * 2,如果连接建立成功,说明数据传输通道已建立. * 该通道就是socket流 ,是底层建立好的. 既然是流,说明这里既有输入,又有输出. * 想要输入或者输出流对象,可以找Socket来获取. * 可以通过getOutputStream(),和getInputStream()来获取两个字节流. * 3,使用输出流

JAVA 通过 Socket 实现 TCP 编程

简介 TCP简介 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP,下一篇博客会实现)是同一层内 另一个重要的传输协议.在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层.不同主机的应用层之间经常需要可靠的.像管道一样的连接,但是I

python编程系列---tcp服务端的简单实现

流程如下: """tcp服务端创建流程1. 创建服务端的tcp socket : server_socket 用于监听客户端的请求2. 绑定端口3. server_socket开启监听,由主动连接模式变为被动接受模式4. 等待接收客户端的请求, 一有连接,则立即响应,且创建一个与客户端对接的socket,用该socket与客户端通信5. 使用新创建的socket与客户端通信6. 关闭新创建的socket, 该socket关闭,则与当前客户端结束通信7. server_sock

进程池与线程池、协程、协程实现TCP服务端并发、IO模型

进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度的利用计算机 什么是池? 在保证计算机硬件安全的情况下最大限度的利用计算机 池其实是降低了程序的运行效率,但是保证了计算机硬件的安全 (硬件的发展跟不上软件的速度) ''' from concurrent.futures import ThreadPoolExecutor import time p