精华内容
下载资源
问答
  • 服务器使用多线程实现与多个客户端通讯实现与代码案例
    千次阅读
    2018-09-15 23:12:29

    1、应用场景

    单实例的服务,实现与多个客户端进行通信。

    2、实现方案

    2.1、服务器端,创建ServerSocket对象,使用死循环调用accept()方法等待客户端请求建立连接;

    2.2、客户端,创建Socket对象,请求与服务器建立连接;

    2.3、服务端接受客户端的请求,并建立专线连接;底层是TCP的链接,即经历过三次握手;

    2.4、建立连接的两个socket在一个单独的线程上对话,可以理解为一个专门的管道;客户端请求携带参数,服务器端对客户端作出响应,并返回参数;

    2.5、服务器端单独开启新的线程,专门实现接受客户端请求和对客户端作出响应;优点:实现异步处理,提高了并发效率。

    2.6、服务器端自动进入下一个循环,继续等待新的连接请求;

    2.7、服务器端增加计数功能,实现累计客户端请求次数。

    注意事项:

    1、先启动服务端,再启动客户端,原因:客户端主动与服务器端建立连接。

    2、服务器端的 ServerSocket 对象示例,不能执行.close();原因:要一直等待客户端请求建立连接。

    3、代码实现

    注明:代码参考慕课网汤小洋老师讲《Java socket 应用》。

    3.1、服务器端

    package com.liuxd.socket;
    
    
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /*
     * 基于TCP协议的Socket通信,实现用户登陆
     * 服务器端
     */
    public class Server {
        public static void main(String[] args) {
            try {
                //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
                ServerSocket serverSocket = new ServerSocket(8901);
                Socket socket = null;
    
                //记录客户端的数量
                AtomicInteger count = new AtomicInteger();
                System.out.println("***服务器即将启动,等待客户端的连接***");
    
                //循环监听等待客户端的连接
                while (true) {
                    //调用accept()方法开始监听,等待客户端的连接
                    socket = serverSocket.accept();
                    //创建一个新的线程
                    ServerThread serverThread = new ServerThread(socket);
                    //启动线程
                    serverThread.start();
    
                    count.incrementAndGet();//统计客户端的数量
                    System.out.println("客户端的数量:" + count.get());
                    InetAddress address = socket.getInetAddress();
                    System.out.println("当前客户端的IP:" + address.getHostAddress());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    3.2、服务器端处理接受参数与对客户端作出响应

    package com.liuxd.socket;
    
    /**
     * Created by Liuxd on 2018/9/15.
     */
    
    import java.io.*;
    import java.net.Socket;
    
    /*
     * 服务器线程处理类
     */
    public class ServerThread extends Thread {
        // 和本线程相关的Socket
        Socket socket = null;
    
        public ServerThread(Socket socket) {
            this.socket = socket;
        }
    
        //线程执行的操作,响应客户端的请求
        public void run() {
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            OutputStream os = null;
            PrintWriter pw = null;
            try {
                //获取输入流,并读取客户端信息
                is = socket.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
                String info;
                while ((info = br.readLine()) != null) {//循环读取客户端的信息
                    System.out.println("我是服务器,客户端说:" + info);
                }
                socket.shutdownInput();//关闭输入流
    
                //获取输出流,响应客户端的请求
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write("欢迎您!");
                pw.flush();//调用flush()方法将缓冲输出
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                //关闭资源
                try {
                    if (pw != null)
                        pw.close();
                    if (os != null)
                        os.close();
                    if (br != null)
                        br.close();
                    if (isr != null)
                        isr.close();
                    if (is != null)
                        is.close();
                    if (socket != null)
                        socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    3.3、客户端

    package com.liuxd.socket;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    /*
     * 客户端
     */
    public class Client {
        public static void main(String[] args) {
            try {
                //1.创建客户端Socket,指定服务器地址和端口
                Socket socket = new Socket("127.0.0.1", 8901);
    
                //2.获取输出流,向服务器端发送信息
                OutputStream os = socket.getOutputStream();//字节输出流
                PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
                pw.write("用户名:alice;密码:789");
                pw.flush();
                socket.shutdownOutput();//关闭输出流
    
                //3.获取输入流,并读取服务器端的响应信息
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String info = null;
                while ((info = br.readLine()) != null) {
                    System.out.println("我是客户端,服务器说:" + info);
                }
    
                //4.关闭资源
                br.close();
                is.close();
                pw.close();
                os.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

     

    更多相关内容
  • 本文实例讲述了Python实现基于线程、用户的FTP服务器客户端功能。分享给大家供大家参考,具体如下: 项目介绍: 1. 用户加密认证 2. 允许同时用户登录 3. 每用户有自己的家目录 ,且只能访问自己的家目录 ...
  • MFC多客户端SOCKET实例

    2018-04-20 21:19:05
    基于MFC的多客户端SOCKET连接,实现了一个服务器多个客户的连接方式,下一步准备实现客户端重连机制
  • 程序包含4个VI,一个服务器,两个客户端,一个VI,测试能用。2013版本
  • 用QT写了的一简单的服务器端和客户端。有基本的图形界面,可以实现相互数据通信
  • Matlab TCP/IP 服务器示例与两个客户端进行通信。 客户端可以来自 python、c++ 或 matlab 等。
  • 不能延迟等待这个客户端接收完毕再接收另一个客户端; 2.客户端不能关闭,一直连接,以防数据遗漏 知识点: 多线程 同时开启多个任务,不用按照程序的执行顺序来; 基本的代码如下: package cn.com.project; ...

    实验对象:
    三个客户端,一个端口对应一个客户端,分别是6020 6080 6021;
    6020 和6021下面没有手环,也就是说没有数据发送过来;
    实验要求:
    1.一个时间点,无论哪个基站有数据发送,服务器必须同时接收。不能延迟等待这个客户端接收完毕再接收另一个客户端;
    2.客户端不能关闭,一直连接,以防数据遗漏
    3.多个客户端,如果只有一个客户端发送数据,会不会等待延迟?
    知识点:
    多线程 同时开启多个任务,不用按照程序的执行顺序来;
    基本的代码如下:

    package cn.com.project;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class Crc{
    	public static StringBuilder stringBuilder=null;
    	public static int i=0;
    	public static int h=0;
    	public static String sz[]=null;
    	//1,循环的基站
    	public static void main(String[] args) {
    		Port();
    				}
    
    public static void Port(){
    	try {
    		new Thread(new ThreadReader(new ServerSocket(6020))).start();
    		new Thread(new ThreadReader(new ServerSocket(6080))).start();
    		new Thread(new ThreadReader(new ServerSocket(6021))).start();
    	} catch (IOException e1) {
    		
    	}
    }
    	}
    
    

    其他的代码见上一篇博客
    实验结果:
    在这里插入图片描述
    在这里插入图片描述
    结论:
    以上程序:
    及时多个客户端只有一个客户端发送数据,也不影响执行时间;
    服务器可以同步接受客户端信息,无延迟;
    客户端可以一直发送数据,即使没有数据也会一直开着的!!
    缺陷:
    一个客户端下面有15个手卡,全部接受完毕需要6分钟,耗时太长!!!

    2018-10.7 续写博客
    这篇博客最大的错误就是对socket接受信号的理解错误!
    一个服务器下面多个基站,一个基站下面多个手卡,只需要建立一次连接,在socket.getInputStream();这里加上while(true){socket.getInputStream();}只要输入流这里有数据输入,就一直接受;
    我之前所有的错误就是在于,不理解这个通信过程!

    2019-1-23再次续写博客
    当然不能关闭流,流关闭了,socket就关闭了!
    这个涉及到socket的长连接!
    如果要求接受数据快,不能有延迟的话,我建议不用socket阻塞嵌套字,因为非常慢,接受某个手卡的数据的第一条和第二条数据相差25秒多!耽误信息的接受,导致定位不准确!

    展开全文
  • 类只用于派生,所以不会生成这类的实例;可以考虑使用TCPServer和UDPServer。 TCPServer/UDPServer:基本的网络同步TCP/UDP服务器。 UnixStreamServer/ UnixDatagramServer:基本的基于文件同步TCP/UDP服务器...
  • 多个客户端 长连接 服务器服务器多线程处理!例子,仅供学习
  • 主要介绍了Python socket网络编程TCP/IP服务器与客户端通信的相关资料,这里对Scoket 进行详解并创建TCP服务器及TCP 客户端实例代码,需要的朋友可以参考下
  • 资源中分别有客户端和服务端,通过TcpListener实现监听客户端访问服务器的端口,并接收数据。
  • 1.TCP实现服务器端与多个客户端通信 import socket def main(): # 1. 创建套接字socket tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2. 绑定本地信息 bind tcp_server_socket...

     1.TCP实现服务器端与多个客户端通信

    import socket
    
    def main():
        # 1. 创建套接字socket
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # 2. 绑定本地信息 bind
        tcp_server_socket.bind(("", 7890))
    
        # 3. 让默认的套接字由主动变为被动 listen
        tcp_server_socket.listen(128)
    
        while True:
            print("等待一个新的客户端的到来...")
            # 4. 等待别人的电话到来(等待客户端的链接 accept)
            new_client_socket, client_addr = tcp_server_socket.accept()
    
            print("一个新的客户端已经到来%s" % str(client_addr))
    
            # 接收客户端发送过来的请求
            recv_data = new_client_socket.recv(1024) #注意这个1024byte,大小根据需求自己设置
            print("客户端福送过来的请求是:%s" % recv_data.decode("utf-8"))
    
            # 回送一部分数据给客户端
            new_client_socket.send("hahahghai-----ok-----".encode("utf-8"))
    
            # 关闭套接字
            # 关闭accept返回的套接字 意味着 不会在为这个客户端服务
            new_client_socket.close()
            print("已经服务器完毕。。。。")
    
        # 如果将监听套接字 关闭了,那么会导致 不能再次等待新客户端的到来,即xxxx.accept就会失败
        tcp_server_socket.close()
    
    
    if __name__ == "__main__":
        main()

    2.TCP实现与多个客户端多次通信

    import socket
    
    def main():
        # 1.创建套接字 socket
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        # 2. 绑定本地信息 bind
        tcp_server_socket.bind(("", 7890))
    
        # 3. 让默认的套接字由主动变为被动 listen
        tcp_server_socket.listen(128)
    
        # 循环目的:调用多次accept,从而为多个客户端服务
        while True:
            print("等待一个新的客户端的到来...")
            # 4. 等待别人的电话到来(等待客户端的链接 accept)
            new_client_socket, client_addr = tcp_server_socket.accept()
    
            print("一个新的客户端已经到来%s" % str(client_addr))
            
            # 循环目的: 为同一个客户端 服务多次
            while True:
                # 接收客户端发送过来的请求
                recv_data = new_client_socket.recv(1024)
                print("客户端福送过来的请求是:%s" % recv_data.decode("utf-8"))
    
                # 如果recv解堵塞,那么有2种方式:
                # 1. 客户端发送过来数据
                # 2. 客户端调用close导致而了 这里 recv解堵塞(客户端主动断开连接)
                if recv_data:
                    # 回送一部分数据给客户端
                    new_client_socket.send("hahahghai-----ok-----".encode("utf-8"))
                else:
                    break
    
            # 关闭套接字
            # 关闭accept返回的套接字 意味着 不会在为这个客户端服务
            new_client_socket.close()
            print("已经为这个客户端服务完毕。。。。")
    
        # 如果将监听套接字 关闭了,那么会导致 不能再次等待新客户端的到来,即xxxx.accept就会失败
        tcp_server_socket.close()
    
    
    if __name__ == "__main__":
        main()
    

    可以通过网络调试助手实现多个客户端同时与其通信,但是问题必须是一个个通信,排队。

    统一声明:关于原创博客内容,可能会有部分内容参考自互联网,如有原创链接会声明引用;如找不到原创链接,在此声明如有侵权请联系删除哈。关于转载博客,如有原创链接会声明;如找不到原创链接,在此声明如有侵权请联系删除哈。 

    展开全文
  • C++实现TCP服务器端同时和多个客户端通信(多线程)

    千次阅读 多人点赞 2021-05-12 15:25:26
    服务器同时可以和多个客户端建立连接,进行交互; 在某次交互中,服务器端或某客户端有一方发送"end"即终止服务器与其的通信;服务器还可以继续接收其他客户端的请求,与其他客户端通信。 服务器端 #include <...

    Windows下的多线程网络通讯


    通讯建立后首先由服务器端发送消息,客户端接收消息;接着客户端发送消息,服务器端接收消息,实现交互发送消息。
    服务器同时可以和 多个客户端建立连接,进行交互;
    在某次交互中,服务器端或某客户端有一方发送"end"即终止服务器与其的通信;服务器还可以继续接收其他客户端的请求,与其他客户端通信。

    服务器端

    #include <WinSock2.h>
    #include <WS2tcpip.h>
    #include <iostream>
    using namespace std;
    #pragma comment(lib, "ws2_32.lib")
    #define PORT 65432
    DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);
    int main() 
    {
    	//初始化winsock2.DLL
    	WSADATA wsaData;
    	WORD wVersionRequested = MAKEWORD(2, 2);
    	if (WSAStartup(wVersionRequested, &wsaData) != 0)
    	{
    		cout << "加载winsock.dll失败!" << endl;
    		return 0;
    	}
    	//创建套接字
    	SOCKET  sock_server;
    	if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
    	{
    		cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
    		WSACleanup();
    		return 0;
    	}
    	//绑定端口和Ip
    	sockaddr_in addr;
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(PORT);
    	inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址
    	if (SOCKET_ERROR == bind(sock_server, (SOCKADDR*)&addr, sizeof(sockaddr_in)))
    	{
    		cout << "地址绑定失败!错误代码:" << WSAGetLastError() << endl;
    		closesocket(sock_server);
    		WSACleanup();
    		return 0;
    	}
    	//将套接字设为监听状态
    	listen(sock_server, 0);
    	
    	//主线程循环接收客户端的连接
    	while (1) 
    	{
    		sockaddr_in addrClient;
    		int len = sizeof(sockaddr_in);
    		//接收成功返回与client通讯的socket
    		SOCKET con = accept(sock_server, (SOCKADDR*)&addrClient, &len);
    		if (con != INVALID_SOCKET) 
    		{
    			//创建线程 并且传入与client通讯的套接字
    			HANDLE hThread = CreateThread(NULL, 0, ThreadFun, (LPVOID)con, 0, NULL);
    			CloseHandle(hThread); //关闭对线程的引用
    		}
    	}
    	closesocket(sock_server);
    	WSACleanup();
    	return 0;
    }
    //线程通讯部分
    DWORD WINAPI ThreadFun(LPVOID lpThreadParameter) 
    {
    	//与客户端通讯 先发送再接收数据
    	SOCKET sock = (SOCKET)lpThreadParameter;
    	cout << "成功和" << sock << "建立连接!" << endl;
    	while (1)
    	{
    		char msgbuffer[1000];//字符缓冲区
    		printf("服务器向%d发送数据:\n", sock);
    		cin.getline(msgbuffer, sizeof(msgbuffer));
    		int size = send(sock, msgbuffer, sizeof(msgbuffer), 0);//给客户端发送一段信息
    		if (strcmp(msgbuffer, "end\0") == 0)
    		{
    			cout << "关闭和" << sock << "的连接!" << endl;
    			return 0;
    		}
    		if (size == SOCKET_ERROR || size == 0)
    		{
    			cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;
    			return 0;
    		}
    		else cout << "信息发送成功!" << endl;
    		
    		//接收客户端数据
    		msgbuffer[999] = { 0 };
    		int ret = recv(sock, msgbuffer, sizeof(msgbuffer), 0);
    		if(ret == SOCKET_ERROR || ret == 0)
    		{
    			cout << sock << "断开了连接!" << endl;
    			break;
    		}
    		else cout << sock << "  说: " << msgbuffer << endl;
    	}
    	return 0;
    }
    

    客户端

    #include <winsock2.h>
    #include <WS2tcpip.h>
    #include <iostream>
    using  namespace std;
    #pragma comment(lib, "ws2_32.lib")
    #define PORT 65432
    int  main() 
    {
    	//初始化winsock2.DLL
    	WSADATA wsaData;
    	WORD wVersionRequested = MAKEWORD(2, 2);
    	if (WSAStartup(wVersionRequested, &wsaData) != 0)
    	{
    		cout << "加载winsock.dll失败!" << endl;
    		return 0;
    	}
    	//创建套接字
    	SOCKET  sock_client; 
    	if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
    	{
    		cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
    		WSACleanup();
    		return 0;
    	}
    	//连接服务器
    	sockaddr_in   addr;
    	addr.sin_family = AF_INET;
    	addr.sin_port = htons(PORT);
    	inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址
    	int len = sizeof(sockaddr_in);
    	if (connect(sock_client, (SOCKADDR*)&addr, len) == SOCKET_ERROR) {
    		cout << "连接失败!错误代码:" << WSAGetLastError() << endl;
    		return 0;
    	}
    	//实现交互部分,客户端先接收后发送数据
    	while (1)
    	{
    		//接收服务端的消息
    		char msgbuffer[1000] = { 0 };
    		int size = recv(sock_client, msgbuffer, sizeof(msgbuffer), 0);
    		if (strcmp(msgbuffer, "end\0") == 0)
    		{
    			cout << "服务器端已经关闭连接!" << endl;
    			break;
    		}
    		if (size < 0)
    		{
    			cout << "接收信息失败!错误代码:" << WSAGetLastError() << endl;
    			break;
    		}
    		else if (size == 0)
    		{
    			cout << "对方已经关闭连接" << endl;
    			break;
    		}
    		else cout << "The message from Server:" << msgbuffer << endl;
    
    		//从键盘输入一行文字发送给服务器
    		msgbuffer[999] =  0 ;
    		cout << "从键盘输入发给服务器的信息:" << endl;
    		cin.getline(msgbuffer, sizeof(msgbuffer));
    		if (strcmp(msgbuffer, "end\0") == 0)
    		{
    			cout << "关闭连接!" << endl;
    			break;
    		}
    		int ret = send(sock_client, msgbuffer, sizeof(msgbuffer), 0);
    		if (ret == SOCKET_ERROR || ret == 0)
    		{
    			cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;
    			break;
    		}
    		else cout << "信息发送成功!" << endl;
    	}
    	closesocket(sock_client);
    	WSACleanup();
    	return 0;
    }
    

    我们用建立连接时服务器端接收的客户端套接字来唯一标识该客户端。
    服务器端可以随时接收客户端的连接并与其进行交互。

    运行实例

    在这里插入图片描述

    实例展示了服务器端和两个客户端通信的运行过程,包括正常交互、交互过程中另一服务器请求建立连接、服务器主动断开连接和客户端主动断开连接等过程。

    展开全文
  • vb.net服务端和客户端的通信实例原码,实测可用,适合入门学习
  • OPC UA服务器/客户端开发工具

    热门讨论 2017-11-01 20:15:23
    转载的,工具包里有三文件夹,第一是OPC UA Client,是OPC UA客户端安装包,可以直接安装运行,可以用来测试服务器,第二是SDK 工具包,里面是基于.NET的OPC UA服务器客户端的开发工具,安装后有很Demo和...
  • 本文实例讲述了python...2. 客户端使用线程,pyinotify监视到文件变化,放到队列中,由另外一线程发送。 上代码: 服务端: # receive file from client and store them into file use asyncore.# #/usr/bin/pyt
  • QT5环境下的Modbus例程,可供工控modbus通信参考。
  • 多个客户端连接服务器的一个小demo,使用hashmap存储客户端及对应的socket实例,swing做的一个简单可视化界面。
  • xust: 基于QT实现MQTT客户端,实现与服务器连接、订阅与发布...1)借助于QT开发环境实现一MQTT客户端; 2) 具备输入服务器地址、端口号及连接功能; 3)具备发布、订阅消息功能。 注:借助“通信猫”作为服务器
  • 实例简介】基于modbus tcp协议下的tcp接口,可以使用多个客户端进行连接【实例截图】【核心代码】//判断端口合法性if (!int.TryParse(textBox2.Text, out int port)){MessageBox.Show("端口输入不正确!");return;...
  • python 实现TCP socket通信和 HTTP服务器服务器客户端通信实例 socket是什么? 由下图可理解:Socket是应用层与TCP/IP协议族通信的中间软件抽象层。 复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组...
  • 服务器开启后肯定是等待多个客户端连接,这里使用一个死循环让服务器一直处于等待别客户端连接的状态,然后每连接一个客户端就开启一个线程接收客户端发来的消息然后广播给每个客户端。 首先是服务端代码: using...
  • 这种方法解决了诸如处理多个EC2实例服务器客户端多个IP地址之类的问题。 因此,当我们尝试从另一个来源访问API时,它也解决了跨来源资源共享(CORS)请求失败的问题。 强调: Docker compose用于编排多个...
  • ServerSocket服务端与客户端通信DEMO,讲述如何使用多线程的方式,使得多个客户端与服务端通信。
  • WebSocket客户端和服务端实例源码

    千次下载 热门讨论 2015-08-14 13:30:01
    众所周知,Web 应用的交互过程通常是客户端通过浏览器发出一请求,服务器端接收请求后进行处理并返回结果给客户端客户端浏览器将信息呈现,这种机制对于信息变化不是特别频繁的应用尚可,但对于实时要求高、海量...
  • C# socket多客户端监听, 功能:监听客户端访问服务器的端口
  •  1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。  2)客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据...
  • c语言socket编程 与服务器长连接的客户端程序
  • 多个客户端通过 TCP 连接到服务器。 第一个连接将成为发送方,发送 UDP 数据包。 服务器处理程序然后将这些 UDP 数据包中继到 UDP 广播套接字,所有其他作为接收方的客户端都可以通过服务器处理程序侦听。 在传输...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 448,134
精华内容 179,253
关键字:

服务器客户端实例多个客户端