通过单击按钮逐行发送文件

时间:2016-09-16 08:18:39

标签: c# asynchronous

服务器连接到多个客户端非常好,但服务器只发送第一行。我希望服务器读取文件并逐行发送到客户端,然后在下一个按钮单击服务器后应发送下一行给客户。有人可以帮忙吗? 客户代码:

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

namespace Client
{
public partial class Form1 : Form
{
    // State object for receiving data from remote device.

    public class StateObject
    {
        // Client socket.
        public Socket workSocket = null;
        // Size of receive buffer.
        public const int BufferSize = 256;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];
        // Received data string.
        public StringBuilder sb = new StringBuilder();
    }

    public delegate void TextManagerDelegate(string text);
    TextManagerDelegate TextHandler;
    private const int port = 15000;
    static Socket client;
    StateObject state;

    // The response from the remote device.
    private String response = String.Empty;
    public Form1()
    {
        InitializeComponent();
        TextHandler = new TextManagerDelegate(TextManager);

    }

    private void TextManager(string text)
    {
        textBox1.AppendText(text + Environment.NewLine);
    }

    private void StartClient()
    {
        // Connect to a remote device.
        try
        {
            // Establish the remote endpoint for the socket.
            // bei Lust und Laune die deprecated warning fixen

            IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket.
            client = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect to the remote endpoint.
            client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);

        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.Message);
        }
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            BeginInvoke(TextHandler, ("Socket connected to " + client.RemoteEndPoint.ToString()));

            // Create the state object.
            state = new StateObject();
            state.workSocket = client;

            // Begin receiving the data from the remote device.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

            // Complete the connection.
            client.EndConnect(ar);

            // Reine demo-message - kann natürlich entfernt werden
            //Send("Blub");
        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.Message);
        }
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the state object and the client socket 
            // from the asynchronous state object.
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            // Read data from the remote device.
            int bytesRead = client.EndReceive(ar);

            if (bytesRead > 0)
            {
                // There might be more data, so store the data received so far.
                // in data sind die neuen daten
                string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                BeginInvoke(TextHandler, ("Received data: " + data));

                // prinzipiell sollte man auch hier beachten, ob der buffer für die datenmenge ausreicht etc.
                // (selbes Spiel wie beim EmpfangsCallback im Server)

                // der im stringbuilder sind sämtliche Daten aktuell konkateniert (weil es bereits im Bsp vorhanden war)
                // man kann den aber auch rauswerfen
                state.sb.Append(data);
                response = state.sb.ToString();
            }
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.Message);
        }
    }

    private void Send(String data)
    {
        string text = MessageBox.Text;
        text = data;
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device.
        client.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), client);
    }

    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device.
            int bytesSent = client.EndSend(ar);
            BeginInvoke(TextHandler, ("Sent " + bytesSent + " bytes to server."));

            // Signal that all bytes have been sent.
        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.Message);
        }
    }


    private void Connect_Click(object sender, EventArgs e)
    {
        StartClient();
    }

    private void Disconnect_Click(object sender, EventArgs e)
    {
        try
        {
            client.Shutdown(SocketShutdown.Both);
            client.Close();
        }
        catch (Exception)
        {

            System.Windows.Forms.MessageBox.Show("Die Verbindung wurde abgebrochen");
        }
    }

    private void SendMessage_Click(object sender, EventArgs e)
    {
        Send(MessageBox.Text);
    }
}
    }

服务器的代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.CompilerServices;
using System.IO;

namespace RanServer
{


public partial class Form1 : Form
{
    public delegate void TextManagerDelegate(string text);
    public ManualResetEvent allDone = new ManualResetEvent(false);

    public List<StateObject> list = new List<StateObject>();

    public Socket listener;

    TextManagerDelegate TextHandler;
    private const int port = 15000;

    public Form1()
    {
        InitializeComponent();
        TextHandler = new TextManagerDelegate(TextManager);
        StartListening();
    }

    public void StartListening()
    {
        // Data buffer for incoming data.
        byte[] bytes = new Byte[1024];

        // Establish the local endpoint for the socket.

        IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);

        // Create a TCP/IP socket.
        listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.
        try
        {
            ShowText.AppendText("\nServer is connected " + localEndPoint + Environment.NewLine);
            listener.Bind(localEndPoint);
            listener.Listen(100);

            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            ShowText.AppendText("Waiting for a connections...");
            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }

    }

    // AcceptCallback wird aufgerufen, wenn ein neuer Client sich verbinden möchte
    public void AcceptCallback(IAsyncResult ar)
    {
        // Signal the main thread to continue.
        allDone.Set();

        // Get the socket that handles the client request.
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = handler;

        list.Add(state);

        BeginInvoke(TextHandler, "\nNew connection established.");

        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);

        listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
    }

    // ReadCallback wird aufgerufen, wenn der Client Daten an den Server geschickt hat
    public void ReadCallback(IAsyncResult ar)
    {

        String content = String.Empty;

        // Retrieve the state object and the handler socket
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;

        // Read data from the client socket. 
        try
        {
            int bytesRead = handler.EndReceive(ar);
            BeginInvoke(TextHandler, ("\nVerbindung zum Client überprüfen!"));
            if (bytesRead > 0)
            {

                string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                BeginInvoke(TextHandler, ("Received " + bytesRead + " bytes from socket: " + data));

                // Der Stringbuilder im StateObjekt (state.sb) wurde vorgesehen falls der buffer nicht ausreicht, um alle Bytes
                // auf einmal zu erhalten. Dann werden die Daten zerstückelt und auf mehrere Messages aufgeteilt.
                // Der Stringbuilder baut diese wieder in einen String zusammen.

                // There  might be more data, so store the data received so far.
                state.sb.Append(data);

                // Check for end-of-file tag. If it is not there, read 
                // more data.
                content = state.sb.ToString();
                //BeginInvoke(TextHandler, ("Total read " + content.Length + " bytes from socket. \n Data : " + content));

                // Für Testzwecke kann man die empfangenen Daten an den Client zurückschicken
                //Send(handler, content);
            }
        }
        catch (Exception)
        {

            MessageBox.Show("Verbindung zum Client " + RuntimeHelpers.GetHashCode(handler) + " wurde abgebrochen");
        }


    }


    // SendCallback wird aufgerufen, wenn der Server Daten an den Client verschickt hat
    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket handler = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device.
            int bytesSent = handler.EndSend(ar);
            //BeginInvoke(TextHandler,("Sent " + bytesSent + " bytes to client(" + RuntimeHelpers.GetHashCode(handler)+ ")."));
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
    }

    //Stoppt die Verbindung und schließt das Programm wenn der Stop-Button geklickt wird. 
    private void StopButton_Click_1(object sender, EventArgs e)
    {
        //Iteriere durch Stateobject-Liste und schließe die einzelnen Sockets
        foreach (StateObject state in list)
        {
            // Löse die verbindung auf
            state.workSocket.Shutdown(SocketShutdown.Both);
            state.workSocket.Close();
            list.Remove(state);
        }

        listener.Close();
    }

    private void Send(Socket handler, String data)
    {
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.ASCII.GetBytes(data);
        BeginInvoke(TextHandler, ("Send data to: " + RuntimeHelpers.GetHashCode(handler)));
        // Begin sending the data to the remote device.
        handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
    }

    // Diese Funktion wird vom Button aufgerufen
    public void SendFilesButton_Click(object sender, EventArgs e)
    {
        // Iteriere durch Stateobject-Liste und schicke an jedem die entsprechenden Daten
        try
        {
            foreach (StateObject state in list)
            {
                string line;
                StreamReader reader = new StreamReader("C:\\Users\\Chudnofsky\\Desktop\\Projekt\\Neu\\MesswerteAnlage.txt");
                line = reader.ReadLine();
                //string data = "foo";
                // den string mit dem Inhalt der jeweiligen nächsten Zeile befüllen
                // die letzte ZeilenNr ist in state.zeilenVerschickt drinnen

                Send(state.workSocket, line);
                state.zeilenVerschickt++;


            }
        }
        catch (Exception)
        {

            MessageBox.Show("Es besteht keine Verbindung zum Client!!!");
        }


    }

    public void TextManager(string txt)
    {
        ShowText.AppendText(Environment.NewLine + txt);
    }
}

public class StateObject
{
    // Client  socket.
    public Socket workSocket = null;
    // Size of receive buffer.
    public const int BufferSize = 1024;
    // Receive buffer.
    public byte[] buffer = new byte[BufferSize];
    // Received data string.
    public StringBuilder sb = new StringBuilder();
    // mitzählen der Anzahl der verschickten Zeilen
    public int zeilenVerschickt = 0;
}
 }

1 个答案:

答案 0 :(得分:1)

每次单击按钮

时,都会初始化一个新的StreamReader
StreamReader reader = new StreamReader("C:\\Users\\Chudnofsky\\Desktop\\Projekt\\Neu\\MesswerteAnlage.txt");