精华内容
下载资源
问答
  •  //打开serverfifo,用于读取客户端的请求  fd = open(FIFO, O_RDONLY);  if (fd ) {  printf("server open fifo error!\n");  return -1;  }  ClientPthread *clpth;  while(true)  { ...

    //client

    #include <iostream>
    #include "App.h"
    #include "stdio.h"
    #include "sys/types.h"
    #include "sys/stat.h"
    #include "fcntl.h"
    #include "string.h"
    #define FIFO "/home/flc/srvfifo.tmp"

    using namespace std;
    int main() {
     Ptrol senp, secvp;
     char buff[1028];
     char recvbuff[1028];
     memset(buff, 0, sizeof(buff));
     memset(recvbuff, 0, sizeof(recvbuff));
     senp.Pid = getpid();
     printf("client prosses id is %d\n", senp.Pid);
     memset(senp.data, 0, sizeof(senp.data));
     memcpy(senp.data, "ghl", sizeof("ghl"));
     memset(senp.pathname, 0, sizeof(senp.pathname));
     snprintf(senp.pathname, sizeof(senp.pathname), "/home/flc/clientfifo.%ld",
       (long) senp.Pid);
     unlink(senp.pathname);
     if (mkfifo(senp.pathname, 0666) < 0) {
      printf("client create fifoc error");
      return -1;
     }
     printf("senp.pathname is %s\n", senp.pathname);
     int fd = open(FIFO, O_WRONLY);
     if (fd < 0) {
      printf("client open fifo error\n");
      return -1;
     }
     memcpy(buff, &senp, sizeof(senp));
     int result = write(fd, buff, sizeof(buff));
     if (result == 1028) {
      int fd1 = open(senp.pathname, O_RDONLY);
      if (fd1 < 0) {
       printf("client open fifoc error\n");
       return -1;
      }
      if (read(fd1, recvbuff, sizeof(recvbuff)) == 1028) {
       memcpy(&secvp, recvbuff, sizeof(secvp));
       printf("client recvbuff p_id %d\n", secvp.Pid);
       printf("client recvbuff is %s\n", secvp.data);
       close(fd1);
       return 0;
      }
     }
     return 0;
    }

    //server

    #include <iostream>
    #include "stdio.h"
    #include "sys/types.h"
    #include "sys/stat.h"
    #include "fcntl.h"
    #include "string.h"
    #include "App.h"
    #include "ClientPthread.h"
    #define FIFO "/home/flc/srvfifo.tmp"
    //#define MAXLINE1 1028;

    using namespace std;

    int main() {
     int fd;
     char readbuff[1028];
     memset(readbuff, 0, sizeof(readbuff));
     unlink(FIFO);
     //创建server-fifo
     if (mkfifo(FIFO, 0666) < 0) {
      printf("server create fifo error!\n");
      return -1;
     }
     //打开serverfifo,用于读取客户端的请求
     fd = open(FIFO, O_RDONLY);
     if (fd < 0) {
      printf("server open fifo error!\n");
      return -1;
     }
     ClientPthread *clpth;
     while(true)
     {
      if(read(fd,readbuff,sizeof(readbuff))>0)
      {
       Ptrol p;
       memcpy(&p,readbuff,sizeof(p));
       clpth= new ClientPthread(p);
       clpth->create();
       close(fd);
      }
     }

     cout << "!!!Hello World!!!" << endl; // prints !!

    //Pthread.h

    #ifndef PTHREAD_H_
    #define PTHREAD_H_
    #include "pthread.h"

    class Pthread {
    public:
     Pthread();
     bool create();
     void join();
     virtual ~Pthread();
     virtual void thread_work();
     static void *wrapper(void *args);
    private:
       pthread_t pthid;
    };

    #endif /* PTHREAD_H_ */

     

    //Pthread.cpp

    #include "Pthread.h"

    Pthread::Pthread() {
     // TODO Auto-generated constructor stub
     this->pthid=-1;
    }
    void Pthread::thread_work(){

    }
    void * Pthread::wrapper(void *args){
        Pthread *pth=static_cast<Pthread *>(args);
        pth->thread_work();
        return NULL;
    }
    void Pthread::join(){
     pthread_join(this->pthid,NULL);
    }
    bool Pthread::create(){
     if(pthread_create(&pthid,NULL,wrapper,this)!=0){
      return false;
     }
     return true;
    }
    Pthread::~Pthread() {
     // TODO Auto-generated destructor stub
    }

    //ClientPthread.h

    #ifndef CLIENTPTHREAD_H_
    #define CLIENTPTHREAD_H_

    #include "Pthread.h"
    #include "App.h"

    class ClientPthread: public Pthread {
    public:
     Ptrol p;
     ClientPthread(Ptrol p);
     void thread_work();
     virtual ~ClientPthread();
    };

    //ClientPthread.cpp

    #include "ClientPthread.h"
    #include "stdio.h"
    #include "sys/types.h"
    #include "sys/stat.h"
    #include "fcntl.h"
    #include "string.h"
    #include "unistd.h"

    ClientPthread::ClientPthread(Ptrol p) {
     // TODO Auto-generated constructor stub
     this->p=p;
    }
    void ClientPthread::thread_work()
    {
     printf("client p_id is %d\n",this->p.pid);
     printf("client pathname is %s\n",this->p.pathname);
     int fd=open(this->p.pathname,O_WRONLY);
     if(fd<0)
     {
      printf("server open client fifo error\n");
      return ;
     }
     char sendbuf[1028];
     memcpy(this->p.data,"recv",sizeof("recv"));
     printf("server send client buff is %s\n",p.data);
     memset(sendbuf,0,sizeof(sendbuf));
     memcpy(sendbuf,&p,sizeof(p));
     int result=write(fd,sendbuf,sizeof(sendbuf));
     printf("server send client result is %d\n",result);

    }

    ClientPthread::~ClientPthread() {
     // TODO Auto-generated destructor stub
    }

    //App.h

    #ifndef APP_H_
    #define APP_H_
    #include "string.h"
    #include "pthread.h"
    class App {
    public:
     App();
     virtual ~App();
    };
    struct Ptrol{
     int pid;
     char pathname[32];
     char data[512];
     void reset(char *buff)
     {
      memcpy(this,buff,strlen(buff));
     }
     void operator =(Ptrol p)
     {
      this->pid=p.pid;
      memset(this->data,0,sizeof(this->data));
      memset(this->pathname,0,sizeof(this->pathname));
      memcpy(this->data,p.data,sizeof(p.data));
      memcpy(this->pathname,p.pathname,sizeof(p.pathname));
     }
    };

    #endif /* APP_H_ */

    //编译完先执行server,然后执行client

    展开全文
  • 本文章向大家介绍C#服务器客户端模型以及网络聊天室实例,主要包括C#服务器客户端模型以及网络聊天室实例使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。...

            本文章向大家介绍C#服务器客户端模型以及网络聊天室实例,主要包括C#服务器客户端模型以及网络聊天室实例使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

            实现了简单的聊天室功能,多个客户端连接一个服务器,客户端和服务器双向收发消息,服务器向所有用户广播消息

    服务器:

    主函数文件

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SeverTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                SeverControl sever = new SeverControl();
                sever.start();
                Console.ReadLine();
            }
        }
    }

    SeverControl类文件

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace SeverTest
    {
        class SeverControl
        {
            private Socket severSocket;
            private List<Socket> clientList;//创建一个socket集合来保存正在连接的客户端
            public SeverControl()
            {
                severSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                clientList = new List<Socket>();
            }
            public void start()
            {
                severSocket.Bind(new IPEndPoint(IPAddress.Any,12581));//设置允许访问ip和端口
                severSocket.Listen(10);//开始监听端口
                Console.WriteLine("服务器启动");
    
                Thread acceptThread = new Thread(Accept);//新建一个线程来接受客户端连接
                acceptThread.IsBackground = true;
                acceptThread.Start();
    
            }
            public void Accept()
            {
                Socket client = severSocket.Accept();
                IPEndPoint point = client.RemoteEndPoint as IPEndPoint;//RemoteEndPoint必须强制转成IPEndPoint
                Console.WriteLine(point.Address + "[" + point.Port + "]" + " 连接成功");
                clientList.Add(client);//将连接保存到集合
    
                Thread receiveThread = new Thread(Receive);//新建一个线程来接收客户端传来的数据
                receiveThread.IsBackground = true;
                receiveThread.Start(client);
                Accept();
            }
            public void Receive(Object obj)//带参数线程函数形传参必须是Object
            {
                byte[] s = new byte[1024];
                Socket client = obj as Socket;
                IPEndPoint point = client.RemoteEndPoint as IPEndPoint;
                //clint.receive方法会挂起线程,当客户端断开连接时会抛出异常
                try { 
                    int msglen = client.Receive(s);//获得客户端传来的数据,以byte数组形式传给s,返回字符串长度
                    string str = point.Address + " 说: " + Encoding.UTF8.GetString(s, 0, msglen);
                    Console.WriteLine(str);
                    BroadCast(client, str);//向所有连接的客户端进行广播
                    Receive(client);
                }
                catch
                {
                    Console.WriteLine(point.Address+"["+point.Port+"]"+"断开");
                    clientList.Remove(client);//将连接从集合移除
                }
            }
            private void BroadCast(Socket clientother,string str)
            {
                foreach(var client in clientList)
                {
                    if (client == clientother)
                    {
                        //本人发出,不回应
                    }
                    else
                    {
                        client.Send(Encoding.UTF8.GetBytes(str));
                    }
                }
            }
        }
    }

    客户端

    主函数文件

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ClientTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                ClientControl client = new ClientControl();
                client.connect("127.0.0.1",12581);
                client.send();
            }
        }
    }

    ClientControl类文件

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ClientTest
    {
        public class ClientControl
        {
            private Socket clientSocket;
            public ClientControl()
            {
                clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            }
            public void connect(string ip,int port)
            {
                clientSocket.Connect(ip,port);
                Console.WriteLine("连接服务器成功");
                Console.WriteLine("输入任意字符聊天,输入quit退出");
                Thread receiveThread = new Thread(Receive);
                receiveThread.IsBackground = true;
                receiveThread.Start();
            }
            private void Receive()
            {
                byte[] s = new byte[1024];
                try
                {
                    int msglen = clientSocket.Receive(s);
                    Console.WriteLine(Encoding.UTF8.GetString(s, 0, msglen));
                    Receive();
                }
                catch
                {
                    Console.WriteLine("服务器关闭");
                }
            }
            public void send()
            {
                Thread srThread = new Thread(SendAndRead);
                srThread.Start();
            }
            private void SendAndRead()
            {
                string s = Console.ReadLine();
                while (s != "quit")
                {
                    clientSocket.Send(Encoding.UTF8.GetBytes(s));
                    s = Console.ReadLine();
                }
            }
        }
    }

    http://www.manongjc.com/article/95316.html

    展开全文
  • 1.创建带连接池的线程文件传输服务器客户端 . 介绍 我们现在已经拥有的 MultithreadedServer 每当有客户机申请一连接时都在一新 Thread 中创建一新 ConnectionHandler。这意味着可能有一捆...

    1.创建带连接池的多线程文件传输服务器和客户端

    . 介绍

    我们现在已经拥有的 MultithreadedServer 每当有客户机申请一个连接时都在一个新 Thread 中创建一个新 ConnectionHandler。这意味着可能有一捆 Thread “躺”在我们周围。而且创建 Thread 的系统开销并不是微不足道的。如果性能成为了问题(也请不要事到临头才意识到它),更高效地处理我们的服务器是件好事。那么,我们如何更高效地管理服务器端呢?我们可以维护一个进入的连接池,一定数量的ConnectionHandler 将为它提供服务。这种设计能带来以下好处:

    • 它限定了允许同时连接的数目。
    • 我们只需启动 ConnectionHandler Thread 一次。

    幸运的是,跟在我们的多线程示例中一样,往代码中添加“池”不需要来一个大改动。事实上,应用程序的客户机端根本就不受影响。在服务器端,我们在服务器启动时创建一定数量的 ConnectionHandler,我们把进入的连接放入“池”中并让 ConnectionHandler 打理剩下的事情。这种设计中有很多我们不打算讨论的可能存在的技巧。例如,我们可以通过限定允许在“池”中建立的连接的数目来拒绝客户机。

    请注意:我们将不会再次讨论 acceptConnections()。这个方法跟前面示例中的完全一样。它无限循环地调用 ServerSocket 上的 accept() 并把连接传递到 handleConnection()

     2. 创建 PooledRemoteFileServer 类

    这里是 PooledRemoteFileServer 类的结构:

    1. import java.io.*;  
    2. import java.net.*;  
    3. import java.util.*;  
    4.   
    5. public class PooledRemoteFileServer {  
    6.     protected int maxConnections;  
    7.     protected int listenPort;  
    8.     protected ServerSocket serverSocket;  
    9.   
    10.     public PooledRemoteFileServer(int aListenPort, int maxConnections) {  
    11.         listenPort = aListenPort;  
    12.         this.maxConnections = maxConnections;  
    13.     }  
    14.     public static void main(String[] args) {  
    15.     }  
    16.     public void setUpHandlers() {  
    17.     }  
    18.     public void acceptConnections() {  
    19.     }  
    20.     protected void handleConnection(Socket incomingConnection) {  
    21.     }  
    22. }  


     

    请注意一下您现在应该熟悉了的 import 语句。我们给类以下实例变量以保存:

    • 我们的服务器能同时处理的活动客户机连接的最大数目

    • 进入的连接的侦听端口(我们没有指定缺省值,但如果您想这样做,并不会受到限制)

    • 将接受客户机连接请求的 ServerSocket

    类的构造器用的参数是侦听端口和连接的最大数目

    我们的类有一个 main() 方法和三个其它方法。稍后我们将探究这些方法的细节。现在只须知道 setUpHandlers() 创建数目为 maxConnections 的大量 PooledConnectionHandler,而其它两个方法则与我们前面已经看到的相似:acceptConnections() 在 ServerSocket 上侦听传入的客户机连接,而 handleConnection 则在客户机连接一旦被建立后就实际处理它。


     3. 实现 main()

    这里我们实现需作改动的 main() 方法,该方法将创建能够处理给定数目的客户机连接的 PooledRemoteFileServer,并告诉它接受连接:

    1. public static void main(String[] args) {  
    2.     PooledRemoteFileServer server = new PooledRemoteFileServer(30003);  
    3.     server.setUpHandlers();  
    4.     server.acceptConnections();  
    5. }  

    我们的 main() 方法很简单。我们实例化一个新的 PooledRemoteFileServer,它将通过调用 setUpHandlers() 来建立三个PooledConnectionHandler。一旦服务器就绪,我们就告诉它 acceptConnections()

     4. 建立连接处理程序

     

    1. public void setUpHandlers() {  
    2.     for (int i = 0; i < maxConnections; i++) {  
    3.         PooledConnectionHandler currentHandler = new PooledConnectionHandler();  
    4.         new Thread(currentHandler, "Handler " + i).start();  
    5.     }  
    6. }  


     

    setUpHandlers() 方法创建 maxConnections(例如 3)个 PooledConnectionHandler 并在新 Thread 中激活它们。用实现了 Runnable 的对象来创建 Thread 使我们可以在 Thread 调用 start() 并且可以期望在 Runnable 上调用了 run()。换句话说,我们的 PooledConnectionHandler 将等着处理进入的连接,每个都在它自己的 Thread 中进行。我们在示例中只创建三个 Thread,而且一旦服务器运行,这就不能被改变。


     5. 处理连接

    这里我们实现需作改动的 handleConnections() 方法,它将委派 PooledConnectionHandler 处理连接:

    1. protected void handleConnection(Socket connectionToHandle) {  
    2. PooledConnectionHandler.processRequest(connectionToHandle);  
    3. }  


     

    我们现在叫 PooledConnectionHandler 处理所有进入的连接(processRequest() 是一个静态方法)。

    这里是 PooledConnectionHandler 类的结构:

    1. import java.io.*;  
    2. import java.net.*;  
    3. import java.util.*;  
    4.   
    5. public class PooledConnectionHandler implements Runnable {  
    6.     protected Socket connection;  
    7.     protected static List pool = new LinkedList();  
    8.   
    9.     public PooledConnectionHandler() {  
    10.     }  
    11.     public void handleConnection() {  
    12.     }  
    13.     public static void processRequest(Socket requestToHandle) {  
    14.     }  
    15.     public void run() {  
    16.     }  
    17. }  


     

    这个助手类与 ConnectionHandler 非常相似,但它带有处理连接池的手段。该类有两个实例变量:

    • connection 是当前正在处理的 Socket
    • 名为 pool 的静态 LinkedList 保存需被处理的连接


     6. 填充连接池

    这里我们实现 PooledConnectionHandler 上的 processRequest() 方法,它将把传入请求添加到池中,并告诉其它正在等待的对象该池已经有一些内容:

    1. public static void processRequest(Socket requestToHandle) {  
    2.     synchronized (pool) {  
    3.         pool.add(pool.size(), requestToHandle);  
    4.         pool.notifyAll();  
    5.     }  
    6. }  


     

    理解这个方法要求有一点关于 Java 的关键字 synchronized 如何工作的背景知识。我们将简要讲述一下线程。

    先来看一些定义:

    • 原子方法。在执行过程中不能被中断的方法(或代码块)
    • 互斥锁。客户机欲执行原子方法时必须获得的单个“锁”

    因此,当对象 A 想使用对象 B 的 synchronized 方法 doSomething() 时,对象 A 必须首先尝试获取对象 B 的互斥锁。是的,这意味着当对象 A 拥有该互斥锁时,没有其它对象可以调用对象 B 上任何其它 synchronized 方法。

    synchronized 块是个稍微有些不同的东西。您可以同步任何对象上的一个块,而不只是在本身的某个方法中含有该块的对象。在我们的示例中,processRequest() 方法包含有一个 pool(请记住它是一个 LinkedList,保存等待处理的连接池)的 synchronized块。我们这样做的原因是确保没有别人能跟我们同时修改连接池。

    既然我们已经保证了我们是唯一“涉水”池中的人,我们就可以把传入的 Socket 添加到 LinkedList 的尾端。一旦我们添加了新的连接,我们就用以下代码通知其它正在等待该池的 Thread,池现在已经可用:

    
    pool.notifyAll();
    
    

    Object 的所有子类都继承这个 notifyAll() 方法。这个方法,连同我们下一屏将要讨论的 wait() 方法一起,就使一个 Thread 能够让另一个Thread 知道一些条件已经具备。这意味着该第二个 Thread 一定正在等待那些条件的满足。


     7. 从池中获取连接

    这里我们实现 PooledConnectionHandler 上需作改动的 run()方法,它将在连接池上等待,并且池中一有连接就处理它:

    1. public void run() {  
    2.         while (true) {  
    3.              synchronized (pool) {  
    4.                   while (pool.isEmpty()) {  
    5.                        try {  
    6.                             pool.wait();  
    7.                        } catch (InterruptedException e) {  
    8.                             return;  
    9.                        }  
    10.                    }  
    11.                    connection = (Socket) pool.remove(0);  
    12.              }  
    13.              handleConnection();  
    14.         }  
    15. }  


     

    回想一下在前一屏讲过的:一个 Thread 正在等待有人通知它连接池方面的条件已经满足了。在我们的示例中,请记住我们有三个PooledConnectionHandler 在等待使用池中的连接。每个 PooledConnectionHandler 都在它自已的 Thread 中运行,并通过调用 pool.wait() 产生阻塞。当我们的 processRequest() 在连接池上调用 notifyAll() 时,所有正在等待的 PooledConnectionHandler 都将得到“池已经可用”的通知。然后各自继续前行调用 pool.wait(),并重新检查 while(pool.isEmpty()) 循环条件。除了一个处理程序,其它池对所有处理程序都将是空的,因此,在调用 pool.wait() 时,除了一个处理程序,其它所有处理程序都将再次产生阻塞。恰巧碰上非空池的处理程序将跳出while(pool.isEmpty()) 循环并攫取池中的第一个连接:

    
    connection = (Socket) pool.remove(0);
    
    

    处理程序一旦有一个连接可以使用,就调用 handleConnection() 处理它。

    在我们的示例中,池中可能永远不会有多个连接,只是因为事情很快就被处理掉了。如果池中有一个以上连接,那么其它处理程序将不必等待新的连接被添加到池。当它们检查 pool.isEmpty() 条件时,将发现其值为假,然后就从池中攫取一个连接并处理它。

    还有另一件事需注意。当 run() 拥有池的互斥锁时,processRequest() 如何能够把连接放到池中呢?答案是对池上的 wait() 的调用释放锁,而wait() 接着就在自己返回之前再次攫取该锁。这就使得池对象的其它同步代码可以获取该锁。

    8. 处理连接:再一次

    这里我们实现需做改动的 handleConnection() 方法,该方法将攫取连接的流,使用它们,并在任务完成之后清除它们:

    1. public void handleConnection() {  
    2.     try {  
    3.         PrintWriter streamWriter = new PrintWriter(connection.getOutputStream());  
    4.         BufferedReader streamReader =  
    5.             new BufferedReader(new InputStreamReader(connection.getInputStream()));  
    6.   
    7.         String fileToRead = streamReader.readLine();  
    8.         BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead));  
    9.   
    10.         String line = null;  
    11.         while ((line = fileReader.readLine()) != null)  
    12.             streamWriter.println(line);  
    13.   
    14.         fileReader.close();  
    15.         streamWriter.close();  
    16.         streamReader.close();  
    17.     } catch (FileNotFoundException e) {  
    18.         System.out.println("Could not find requested file on the server.");  
    19.     } catch (IOException e) {  
    20.         System.out.println("Error handling a client: " + e);  
    21.     }  
    22. }  


     

    跟在多线程服务器中不同,我们的 PooledConnectionHandler 有一个 handleConnection() 方法。这个方法的代码跟非池式的 ConnectionHandler 上的 run() 方法的代码完全一样。首先,我们把 OutputStream 和 InputStream 分别包装进(用 Socket 上的 getOutputStream() 和getInputStream()BufferedReader 和 PrintWriter。然后我们逐行读目标文件,就象我们在多线程示例中做的那样。再一次,我们获取一些字节之后就把它们放到本地的 line 变量中,然后写出到客户机。完成读写操作之后,我们关闭 FileReader 和打开的流。


    9. 总结一下带有连接池的服务器 

    我们的带有连接池的服务器研究完了。让我们回顾一下创建和使用“池版”服务器的步骤:

    1. 创建一个新种类的连接处理程序(我们称之为 PooledConnectionHandler)来处理池中的连接。

    2. 修改服务器以创建和使用一组 PooledConnectionHandler

       附: PooledRemoteFileServer 的完整代码清单

    1. import java.io.*;  
    2. import java.net.*;  
    3. import java.util.*;  
    4.   
    5. public class PooledRemoteFileServer {  
    6.     protected int maxConnections;  
    7.     protected int listenPort;  
    8.     protected ServerSocket serverSocket;  
    9.     public PooledRemoteFileServer(int aListenPort, int maxConnections) {  
    10.         listenPort = aListenPort;  
    11.         this.maxConnections = maxConnections;  
    12.     }  
    13.     public void acceptConnections() {  
    14.         try {  
    15.             ServerSocket server = new ServerSocket(listenPort, 5);  
    16.             Socket incomingConnection = null;  
    17.             while (true) {  
    18.                 incomingConnection = server.accept();  
    19.                 handleConnection(incomingConnection);  
    20.             }  
    21.         } catch (BindException e) {  
    22.             System.out.println("Unable to bind to port " + listenPort);  
    23.         } catch (IOException e) {  
    24.             System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);  
    25.         }  
    26.     }  
    27.     protected void handleConnection(Socket connectionToHandle) {  
    28.         PooledConnectionHandler.processRequest(connectionToHandle);  
    29.     }  
    30.     public static void main(String[] args) {  
    31.         PooledRemoteFileServer server = new PooledRemoteFileServer(30003);  
    32.         server.setUpHandlers();  
    33.         server.acceptConnections();  
    34.     }  
    35.     public void setUpHandlers() {  
    36.         for (int i = 0; i < maxConnections; i++) {  
    37.             PooledConnectionHandler currentHandler = new PooledConnectionHandler();  
    38.             new Thread(currentHandler, "Handler " + i).start();  
    39.         }  
    40.     }  
    41. }  


    PooledConnectionHandler 的完整代码清单

     

    1. import java.io.*;  
    2. import java.net.*;  
    3. import java.util.*;  
    4.   
    5. public class PooledConnectionHandler implements Runnable {  
    6.     protected Socket connection;  
    7.     protected static List pool = new LinkedList();  
    8.     public PooledConnectionHandler() {  
    9.     }  
    10.     public void handleConnection() {  
    11.         try {  
    12.             PrintWriter streamWriter = new PrintWriter(connection.getOutputStream());  
    13.             BufferedReader streamReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));  
    14.   
    15.             String fileToRead = streamReader.readLine();  
    16.             BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead));  
    17.   
    18.             String line = null;  
    19.             while ((line = fileReader.readLine()) != null)  
    20.                 streamWriter.println(line);  
    21.   
    22.             fileReader.close();  
    23.             streamWriter.close();  
    24.             streamReader.close();  
    25.         } catch (FileNotFoundException e) {  
    26.             System.out.println("Could not find requested file on the server.");  
    27.         } catch (IOException e) {  
    28.             System.out.println("Error handling a client: " + e);  
    29.         }  
    30.     }  
    31.     public static void processRequest(Socket requestToHandle) {  
    32.         synchronized (pool) {  
    33.             pool.add(pool.size(), requestToHandle);  
    34.             pool.notifyAll();  
    35.         }  
    36.     }  
    37.     public void run() {  
    38.         while (true) {  
    39.             synchronized (pool) {  
    40.                 while (pool.isEmpty()) {  
    41.                     try {  
    42.                         pool.wait();  
    43.                     } catch (InterruptedException e) {  
    44.                         return;  
    45.                     }  
    46.                 }  
    47.                 connection = (Socket) pool.remove(0);  
    48.             }  
    49.             handleConnection();  
    50.         }  
    51.     }  
    52. }  

    2.嵌套字的实际运用案例


     1. 介绍

    我们到目前为止讨论过的示例已经涵盖了 Java 编程的套接字机制,但在“现实”的一些例子中如何使用它们呢?即便用了多线程和带有连接池,如此简单地使用套接字,在多数应用程序中仍然是不合适的。相反地,在构成您的问题域的模型的其它类中使用套接字可能是明智的。

    最近我们在把一个应用程序从大型机/SNA 环境移植到 TCP/IP 环境时就是这样做的。该应用程序的工作是简化零售渠道(例如硬件商店)和金融机构之间的通信。我们的应用程序是中间人。同样地,它必须与一端的零售渠道和另一端的金融渠道通信。我们必须处理客户机通过套接字与服务器进行的交谈,我们还必须把域对象转换成套接字就绪的形式以进行传输。

    我们不能在本教程中涵盖这个应用程序的所有细节,但我们将带您浏览一些高层概念。您可以据此对您自己的问题域做些推断。

     2. 客户机端

    在客户机端,我们系统中的主角是 SocketClientSocketFacade 和 StreamAdapter。客户机端的 UML 如下图所示:

    我们创建了一个 ClientSocketFacade,它是 Runnable 的并且拥有一个 Socket 实例。我们的应用程序可以用一个特定的主机 IP 地址和端口号来实例化一个 ClientSocketFacade,并在一个新 Thread 中运行它。ClientSocketFacade 的 run() 方法调用 connect()connect() 惰性初始化一个Socket。有了 Socket 实例,我们的 ClientSocketFacade 就调用自己的 receive()receive() 将造成阻塞直到服务器在 Socket 上发送数据。一旦服务器发送数据,我们的 ClientSocketFacade 就将醒来并处理传入的数据。数据的发送是直接的。我们的应用程序可以通过用一个 StreamObject调用 send() 方法来简单地告诉它的 ClientSocketFacade 把数据发送到服务器。

    上述讨论中唯一遗漏的一个是 StreamAdapter。当应用程序告诉 ClientSocketFacade 发送数据时,该 Facade 将委派 StreamAdapter 的实例处理有关操作。ClientSocketFacade 委派 StreamAdapter 的同一个实例处理接收数据的操作。StreamAdapter 把消息加工成最终格式并将它放到 Socket 的OutputStream 上,并以逆过程处理从 Socket 的 InputStream 传入的消息。

    例如,或许您的服务器需要知道发送中的消息的字节数。StreamAdapter 可以在发送之前计算消息的长度并将它附加在消息的前端。当服务器接收消息时,同样的 StreamAdapter 能够剥离长度信息并读取正确数量的字节以构建一个 StreamReadyObject


     

     3. 服务器端

    服务器端的情形差不多

    我们把 ServerSocket 包装进 ServerSocketFacadeServerSocketFacade 是 Runnable 的并且拥有一个 ServerSocket 实例。我们的应用程序可以用一个特定的服务器端侦听端口和客户机连接的最大允许数目(缺省值是 50)来实例化一个 ServerSocketFacade。应用程序然后在一个新 Thread 中运行 Facade 以隐藏 ServerSocket 的交互操作细节。

    ServerSocketFacade 上的 run() 方法调用 acceptConnections()acceptConnections() 创建一个新的 ServerSocket,并调用 ServerSocket 上的accept() 以造成阻塞直到有客户机请求一个连接。每当有客户机请求连接,我们的 ServerSocketFacade 就醒来并通过调用 handleSocket() 来把accept() 返回的新 Socket 传递给 SocketHandler 的实例。SocketHandler 的分内工作是处理从客户机到服务器的新通道。


     

     4. 业务逻辑

    一旦我们正确布置了这些 Socket Facade,实现应用程序的业务逻辑就变得容易多了。我们的应用程序使用 ClientSocketFacade 的一个实例来在 Socket 上把数据发送到服务器并取回响应。应用程序负责把我们的域对象转换成 ClientSocketFacade 理解的格式并根据响应构建域对象。


     5. 发送消息到服务器

    下图显示我们的应用程序发送消息的 UML 交互作用图:

    为简单起见,我们未显示 aClientSocketFacade 向它的 Socket 实例请求其 OutputStream 的交互作用(用 getOutputStream() 方法)。一旦我们有了一个 OutputStream 引用,我们就如图所示那样与它交互。请注意 ClientSocketFacade 对我们的应用程序隐藏了套接字交互作用的低级细节。我们的应用程序与 aClientSocketFacade 交互,而不与任何更低级类交互,这些类使把字节放到 Socket OutputStream 上更容易。

     6. 接收来自服务器的消息

    下图显示我们的应用程序接收消息的 UML 交互作用图:

     

     

     

    请注意我们的应用程序在一个 Thread 中运行 aClientSocketFacade。当 aClientSocketFacade 启动时,它告诉自己在自己的 Socket 实例的InputStream 上进行 receive()receive() 方法调用 InputStream 自身的 read(byte[])read([]) 方法将造成阻塞直到它接收到数据,并把在InputStream 接收到的数据放到一个 byte 数组中。当数据到来时,aClientSocketFacade 用 aStreamAdapter 和 aDomainAdapter 构造(最终地)应用程序能够使用的域对象。接着它把该域对象传回给应用程序。再一次,我们的 ClientSocketFacade 对应用程序隐藏了更低级细节,从而简化了应用层。


    总结

    Java 语言简化了套接字在应用程序中的使用。它的基础实际上是 java.net 包中的 Socket 和 ServerSocket 类。一旦您理解了表象背后发生的情况,就能容易地使用这些类。在现实生活中使用套接字只是这样一件事,即通过贯彻优秀的 OO 设计原则来保护应用程序中各层间的封装。我们为您展示了一些有帮助的类。这些类的结构对我们的应用程序隐藏了 Socket 交互作用的低级细节 ― 使应用程序能只使用可插入的ClientSocketFacade 和 ServerSocketFacade。在有些地方(在 Facade 内),您仍然必须管理稍显杂乱的字节细节,但您只须做一次就可以了。更好的是,您可以在将来的项目中重用这些低级别的助手类。




    展开全文
  • 不能延迟等待这个客户端接收完毕再接收另一个客户端; 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秒多!耽误信息的接受,导致定位不准确!

    展开全文
  • 本文实例讲述了Python实现基于线程、用户的FTP服务器客户端功能。分享给大家供大家参考,具体如下: 项目介绍: 1. 用户加密认证 2. 允许同时用户登录 3. 每用户有自己的家目录 ,且只能访问自己的家目录 ...
  • 下面展示一个多客户端的Socket编程实例,例子很简单,要实现多客户端通信,就只能借助于线程技术,其实就是将Socket通信代码写在run()方法中,由于测试代码并非是真正的台计算机与一个服务器相连,所以并不能在...
  • MFC多客户端SOCKET实例

    2018-04-20 21:19:05
    基于MFC的多客户端SOCKET连接,实现了一个服务器多个客户的连接方式,下一步准备实现客户端重连机制
  • 这是一利用 线程,SOCKET,I/O 简易制作的服务器客户端之间的通讯实例,结构清晰明朗,非常适合初学者研究学习之用。
  • 服务器同时可以和多个客户端建立连接,进行交互; 在某次交互中,服务器端或某客户端有一方发送"end"即终止服务器与其的通信;服务器还可以继续接收其他客户端的请求,与其他客户端通信。 服务器端 #include <...
  • 这是一非常简单的通信程序,不需要什么前奏来说明这问题,可以直接来看程序的实现,首先是服务器端的程序:int main(int argc, char **argv){ WSADATA wsd; SOCKET sListen, sClient; int iAddrSize; HANDLE...
  • Android通过get,post方式客户端服务器端交互实例,一简单的demo,在客户端中输入参数,传给服务器端并打印出来.zip,太无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • if(n==0) //说明客户端关闭连接 { res=epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);//将该文件描述符从红黑树中摘除 /* if(res==-1) { perror("epoll_ctl error!!!\n"); exit(1);...
  • 服务器端模拟SFS2X的一些实用功能对mina框架作了一定的封装,使用起来己经和SFS2X没有 太多的区别,但客户端只能使用mina组件(也就是说只能...客户端可以模拟多个实例服务器连接,方便测试,感觉mina的性能还是不错的
  • 服务器端代码: /************************************************** ##filename : server.c ##author : GYZ ##e-mail : 1746902011@qq.com   ##create...
  • socket多客户端连接服务器

    千次阅读 2016-06-01 16:20:53
    socket多客户端连接服务器  关于套接字编程,我们可以使用它来完成...服务器实例化serversocket,并监听本机自定义端口,等待客户端的连接,在这里,当然我们可以为其开一线程来完成其工作。  (*)为何使用线程?
  • 不过大多数都是简单讲解单客户端和服务端通信的实例,这里主要给大家展现一下在.net平台上用窗体程序实现的过程,不过比较有特点的是会告诉大家如何实现不同客户端之间的通信,它们如何通过一服务端准确的找到对方...
  • 基于主题的WebSocket用例:根据服务器上发生的事件,来自UI的另一个实例或IoT设备的数据等将内容推送到Web应用程序UI。 Java WebSocket服务器 看看 Node.js WebSocket服务器 看看 AWS Lambda无服务器WebSocket...
  • 程序的主要功能是:(1)服务器可以以线程的方式应答客户端的请求。(2)以JFrame方式作了Socket客户端,用户可以输入IP地址以端口号9999(可以修改)和服务器通讯。用户使用textArea多行编辑器与服务器通讯。以单独...
  • 假设我有两个客户端连接了WebSocket服务器:我用下图两个Chrome tab表示: 假设KOI app扫码后,发送一个HTTP 请求到WebSocket服务器。 WebSocket的这段代码接收到这个请求,在routeService.js里实现的HTTP请求回调...
  • 本项目使用C#语言建立一TCP通讯实例,并可以互相传递消息: 传送一下传智播客赵老师的视频课程 关键词解释: (1)TCP协议 一种可以用于网络通信的数据传输协议,传输安全可靠不会有信息丢失,重点理解三次握手...
  • 多个客户端连接服务器的一个小demo,使用hashmap存储客户端及对应的socket实例,swing做的一个简单可视化界面。
  • 实例的服务,实现与多个客户端进行通信。 2、实现方案 2.1、服务器端,创建ServerSocket对象,使用死循环调用accept()方法等待客户端请求建立连接; 2.2、客户端,创建Socket对象,请求与服务器建立连接; 2.3...
  • 我们不可能只做一个项目,因此,就需要在客户端查看多个数据库服务端的数据库。那么,怎样在客户端快速配置呢?下面就是解决办法。 在oracle客户端的安装目录K:\oracle\product\10.2.0\client_1\NETWORK\ADMIN下,...
  • 在本节中,我们讲授基本的客户端服务器模型,并通过协作益智游戏获得多个实例连接。 欢迎您下载,分叉或使用所有其他合法方法来处理所有文件! 真正的价值在于此仓库随附的大量高质量的在线教程。 您可以在此处...
  • 这种方法解决了诸如处理多个EC2实例服务器客户端多个IP地址之类的问题。 因此,当我们尝试从另一个来源访问API时,它也解决了跨来源资源共享(CORS)请求失败的问题。 强调: Docker compose用于编排多个...
  • OctoFarm是易于设置和安装的Web服务器客户端,用于统一Octoprint的多个实例。您可以从单个界面管理和监视任意数量的实例,从而完全控制3D打印机群。 · 目录 关于该项目 OctoFarm的创建是为了满足拥有多台具有...
  • 非阻塞方式网络通讯服务器端客户端运行实例 笔记记录:2021-5-21 本来要出一篇非阻塞 但是最后调试还是出现问题,原因是非阻塞方式和recv和send的...服务器同时可以和多个客户端建立连接,进行交互; 在某次交互中,
  • 依次启动Orchestra,websocket server for...启动本地的web Shop模拟器,启动两个,模拟一个user和多个web shop实例的场景。 分别点两次KOI Login按钮,得到两个不同的transaction id: 分别把这两个transaction...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,692
精华内容 1,076
关键字:

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