客户端服务器 Winform IPC 和东西

Posted

技术标签:

【中文标题】客户端服务器 Winform IPC 和东西【英文标题】:Client Server Winform IPC and stuff 【发布时间】:2013-08-19 07:29:04 【问题描述】:

抱歉,标题不那么描述性或贴切,但我一直在尝试这样做一段时间,但没有任何效果,它对我来说很重要。我有一个聊天服务器(控制台应用程序)和一个聊天客户端(winform 应用程序)(参考:http://csharp.net-informations.com/communications/csharp-chat-server-programming.htm)和一个单独的 winform 应用程序,它上面只有一个按钮。每当有任何新消息并且客户端窗口最小化时,我希望那个单独的 winform 上的按钮变成红色。一旦客户端窗口恢复或最大化,它就会变回黄色,这也是按钮的原始颜色。我能够在收到消息时实现颜色的变化,但不考虑最小化状态等。如果我尝试使用 IsIconic 做到这一点,则不会发生任何事情。我所做的是在服务器应用程序中获取客户端 winform 的句柄并检查它是否为 Iconic。请指导,因为我坚持了一段时间。代码如下:

服务器应用程序:

using System;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Net;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Diagnostics;


namespace ConsoleApplication1


    class Program
    

        public static Hashtable clientsList = new Hashtable();

        public static void Main()
        
            string mutex_id = "MY_APP";
            using (Mutex mutex = new Mutex(false, mutex_id))
            
                if (!mutex.WaitOne(0, false))
                
                    return;
                

                var loaclAddress = IPAddress.Parse("127.0.0.1");
                var serverSocket = new TcpListener(loaclAddress, 81);
                /*
                TcpListener serverSocket = new TcpListener(8888);

                */

                TcpClient clientSocket = default(TcpClient);
                int counter = 0;
                serverSocket.Start();
                Console.WriteLine("Chat Server Started ....");
                counter = 0;

                while ((true))
                
                    counter += 1;
                    clientSocket = serverSocket.AcceptTcpClient();
                    byte[] bytesFrom = new byte[10025];
                    string dataFromClient = null;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    clientsList.Add(dataFromClient, clientSocket);
                    broadcast(dataFromClient + " Joined ", dataFromClient, false);
                    Console.WriteLine(dataFromClient + " Joined chat room ");
                    handleClinet client = new handleClinet();
                    client.startClient(clientSocket, dataFromClient, clientsList);
                
                clientSocket.Close();
                serverSocket.Stop();
                Console.WriteLine("exit");
                Console.ReadLine();

            

        

        public static void broadcast(string msg, string uName, bool flag)
        

            foreach (DictionaryEntry Item in clientsList)
            

                TcpClient broadcastSocket;
                broadcastSocket = (TcpClient)Item.Value;
                NetworkStream broadcastStream = broadcastSocket.GetStream();
                Byte[] broadcastBytes = null;
                if (flag == true)
                
                    broadcastBytes = Encoding.ASCII.GetBytes(uName + " says : " + msg);
                
                else
                
                    broadcastBytes = Encoding.ASCII.GetBytes(msg);
                
                broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                broadcastStream.Flush();
            

          //end broadcast function

    //end Main class





    public class handleClinet
    

        //This is used to send custom message to your Winforms
        [DllImport("user32")]
        private static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
        //This is used to find your winforms window
        [DllImport("user32", CharSet = CharSet.Auto)]
        private static extern IntPtr FindWindow(string className, string windowName);
        //This is used to register custom message so that it's ensured to be unique
        [DllImport("user32")]
        private static extern int RegisterWindowMessage(string msgName);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool IsIconic(IntPtr hWnd);


        TcpClient clientSocket;
        string clNo;
        Hashtable clientsList;

        public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
        

            this.clientSocket = inClientSocket;
            this.clNo = clineNo;
            this.clientsList = cList;
            Thread ctThread = new Thread(doChat);
            ctThread.Start();
        

        private void doChat()
        

            int requestCount = 0;
            byte[] bytesFrom = new byte[10025];
            string dataFromClient = null;
            Byte[] sendBytes = null;
            string serverResponse = null;
            string rCount = null;
            requestCount = 0;

            while ((true))
            
                try
                
                    requestCount = requestCount + 1;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    Console.WriteLine("From client - " + clNo + " : " + dataFromClient);

                    int msg = 0;
                    IntPtr hwnd = IntPtr.Zero;
                    int red = RegisterColorCode(Color.Red);
                    //Console.WriteLine(red);
                    int yellow = RegisterColorCode(Color.Yellow);
                    //Console.WriteLine(yellow);
                    msg = 49806;
                    if (hwnd == IntPtr.Zero)
                        hwnd = FindWindow(null, "Winforms Application");
                    IntPtr hwnd1 = FindWindow(null, "ClientApp");

                    if (IsIconic(hwnd1)) //this if-else seems to have no effect as no color changes in the button on the winform
                    
                        if (hwnd != IntPtr.Zero)
                            SetBackColor(hwnd, msg);
                    
                    else
                    
                        msg = 50054;
                        SetBackColor(hwnd, msg);
                    

                    //SetBackColor(hwnd, msg); 
                    //If i write only this then color changes but not on minized state its changed once and for all...
                    //what i want is for the previous if else condition to work**

                    hwnd1 = IntPtr.Zero;


                    rCount = Convert.ToString(requestCount);
                    Program.broadcast(dataFromClient, clNo, true);

                    hwnd = IntPtr.Zero;
                
                catch (Exception ex)
                

                    Console.WriteLine(ex.ToString());

                

            //end while

        //end doChat

        static int RegisterColorCode(Color c)
        
            return RegisterWindowMessage(c.ToString());
        


        static void SetBackColor(IntPtr hwnd, int colorCode)
        
            SendMessage(hwnd, colorCode, IntPtr.Zero, IntPtr.Zero);
        


     //end class handleClinet

//end namespace

客户端应用程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;

namespace chatClient

    public partial class Form1 : Form
    

        TcpClient clientSocket = new System.Net.Sockets.TcpClient();
        NetworkStream serverStream;//new NetworkStream(clientSocket); //default(NetworkStream);
        string readData = null;

        public Form1()
        
            InitializeComponent();
            Text = "ClientApp";
        

        private void Form1_Load(object sender, EventArgs e)
        

        


        private void button1_Click(object sender, EventArgs e)
        

            byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();
        

        private void button2_Click(object sender, EventArgs e)
        
            readData = "Conected to Chat Server ...";
            msg();
            clientSocket.Connect("127.0.0.1", 81);
            serverStream = clientSocket.GetStream();

            byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox3.Text + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            Thread ctThread = new Thread(getMessage);
            ctThread.Start();

            button2.Enabled = false;
        

        private void getMessage()
        
            while (true)
            
                serverStream = clientSocket.GetStream();
                int buffSize = 0;
                byte[] inStream = new byte[10025];
                buffSize = clientSocket.ReceiveBufferSize;
                serverStream.Read(inStream, 0, buffSize);
                string returndata = System.Text.Encoding.ASCII.GetString(inStream);
                readData = "" + returndata;
                msg();
            
        

        private void msg()
        
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(msg));
            else
                textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + readData;
        

        private void textBox2_TextChanged(object sender, EventArgs e)
        

         

    

上面有按钮的 Winform 应用程序:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace consoleMR

    public partial class Form1 : Form
    
        [DllImport("user32")]
        private static extern int RegisterWindowMessage(string msgName);

        int red, yellow;

        public Form1()
        
            InitializeComponent();

            red = RegisterColorCode(Color.Red);
            yellow = RegisterColorCode(Color.Yellow);
            //Set your form caption to a specified (must be unique at the time it runs)
            Text = "Winforms Application";
        

        private int RegisterColorCode(Color c)
        
            return RegisterWindowMessage(c.ToString());
        

        private const int WM_SYSCOMMAND = 0x0112;
        private const int SC_MINIMIZE = 0xf020;
        private const int SC_MAXIMIZE = 0xf030;
        private const int SC_RESTORE = 0xF120;



        protected override void WndProc(ref Message m)
        

            if (m.Msg == WM_SYSCOMMAND)
            
                if (m.WParam.ToInt32() == SC_MAXIMIZE || m.WParam.ToInt32() == SC_RESTORE)
                

                    button1.BackColor = Color.Yellow;
                    this.WindowState = FormWindowState.Maximized;
                    return;
                
            
            switch (m.Msg)
            
                case 49806:
                    button1.BackColor = Color.Red;
                    return;
                case 570445:
                    button1.BackColor = Color.Yellow;
                    return;
            
            base.WndProc(ref m);
        

        private void buttonUCT_Click(object sender, EventArgs e)
        
            Process.Start("C:\\Users\\MainUser\\Documents\\Visual Studio 2010\\Projects\\chatServer\\chatServer\\bin\\Debug\\chatServer.exe");
        

    

我已经坚持了一段时间,非常感谢任何帮助或示例代码或代码更正......真的任何东西

【问题讨论】:

请注意,在上面显示的代码中,您在 winform 应用程序中使用 570445 作为黄色,在服务器应用程序中使用 50054 作为黄色。 (可能是错字) 确实是一个错字...非常感谢 【参考方案1】:

如果我理解正确,您希望能够发送消息以仅在最小化时更改颜色。 要在窗口最小化时更改颜色,请尝试:

编辑(这将查看窗口是否可见 - 不确定是否已最小化):

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWindowVisible(IntPtr hWnd);

    msg = REDMESSAGE;
    if (hwnd == IntPtr.Zero)
        hwnd = FindWindow(null, "Winforms Application");
    IntPtr hwnd1 = FindWindow(null, "ClientApp");

    if (IsWindowVisible(hwnd1))
    
         if (hwnd != IntPtr.Zero)
              SetBackColor(hwnd, msg);
    
    else
    
         msg = YELLOWMESSAGE;
         SetBackColor(hwnd, msg);
    

【讨论】:

是的,您了解问题,但我无法获得您的解决方案...我如何在服务器中使用 if (WindowState == FormWindowState.Minimized) if (hwnd != IntPtr.Zero) SetBackColor (hwnd,味精); 其他 味精 = 黄色消息; SetBackColor(hwnd,味精);您没有在任何地方使用 hwnd1...请指导 我现在明白了;您想要客户端的最小化状态 - 而不是服务器。考虑在最小化时从客户端向服务器发送一条消息,如下所示:private void Form1_Resize ( object sender , EventArgs e ) if ( WindowState == FormWindowState.Minimized ) // SEND MESSAGE TO SERVER else //SEND MESSAGE 'NOT MIN' 然后存储最后一个状态。 我试图在服务器上获取客户端窗口的句柄,然后以某种方式检查它是否已最小化...原因可能有很多客户端在他们自己和所有客户端之间进行通信消息通过服务器...因此,每当服务器从客户端收到任何消息时,在广播该消息之前,它会检查所有打开的客户端,如果任何一个客户端被最小化,则它将消息传递给有关颜色的 winform改变 我明白了;我已经编辑了检查窗口的“可见性”;这是我目前能做的最好的事情。我不明白为什么你的IsIconic 不起作用;也许问题出在其他地方

以上是关于客户端服务器 Winform IPC 和东西的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Java 客户端和 Python 服务器通过套接字创建 IPC?

windows服务或winform来做WCF服务宿主的问题

如何在不同进程中从远程服务向 IPC 客户端发送数据

同一台机器上的IPC...WCF

ANSI C 中的双向 IPC

简单的 Linux IPC 问题