问:
C# multithreading chat server, handle disconnect
I'm looking for a way to handle a disconnect, because every time I close a client, the server stops working. I get an error message, that it is "unable to read beyond the end of the stream" in this line:

```<code>string message = reader.ReadString();
</code>```

Also I need a way to delet the disconnected client from the clients list.
Here is my code:
Server

```<code>using System;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Collections.Generic;

namespace Server
{
    class Server
    {
    public static List<TcpClient> clients = new List<TcpClient>();

    static void Main(string[] args)
    {
        IPAddress ip = IPAddress.Parse("127.0.0.1");
        TcpListener ServerSocket = new TcpListener(ip, 14000);
        ServerSocket.Start();

        Console.WriteLine("Server started.");
        while (true)
        {
            TcpClient clientSocket = ServerSocket.AcceptTcpClient();
            clients.Add(clientSocket);
            handleClient client = new handleClient();
            client.startClient(clientSocket);
        }
    }
}

public class handleClient
{
    TcpClient clientSocket;
    public void startClient(TcpClient inClientSocket)
    {
        this.clientSocket = inClientSocket;
        Thread ctThread = new Thread(Chat);
        ctThread.Start();
    }

    private void Chat()
    {
        while (true)
        {
            BinaryReader reader = new BinaryReader(clientSocket.GetStream());
            while (true)
            {
                string message = reader.ReadString();
                foreach (var client in Server.clients)
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(message);
                }
            }
        }
    }
}
}
</code>```

Client

```<code>using System;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Client
{
   class Client
   {
       public static void Write()
       {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        while (true)
        {
            string str = Console.ReadLine();
            BinaryWriter writer = new BinaryWriter(client.GetStream());
            writer.Write(str);
        }
    }

    public static void Read()
    {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        while (true)
        {
            BinaryReader reader = new BinaryReader(client.GetStream());
            Console.WriteLine(reader.ReadString());
        }
    }

    static void Main(string[] args)
    {
        Thread Thread = new Thread(Write);
        Thread Thread2 = new Thread(Read);
        Thread.Start();
        Thread2.Start();
    }
}
}
</code>```

答:
every time I close a client, the server stops working. I get an error message, that it is "unable to read beyond the end of the stream"

This is, in some sense, completely normal. That is, when using BinaryReader, its normal behavior is to throw EndOfStreamException when reaching the end-of-stream.

Why did it reach end-of-stream? Well, because the client disconnected and that's what happens to the stream. At the socket level, what really happens is that a read operation completes with 0 as the count of bytes read. This is the indication that the client has gracefully closed the socket and will not be sending any more data.

In the .NET API, this is translated to the end of the NetworkStream that TcpClient uses to wrap the Socket object that's actually handling the network I/O. And this NetworkStream object is in turn being wrapped by your BinaryReader object. And BinaryReader throws that exception when it reaches the end of the stream.

Note that your code does not actually provide a graceful way for the user to close a client. They will have to use Ctrl+C, or kill the process outright. Using the former has the serendipitous effect of performing a graceful shutdown of the socket, but only because .NET is handling the termination of the process and runs finalizers on your objects, such as the TcpClient object used to connect to the server, and the finalizer calls Socket.Shutdown() to tell the server it's closing.

If you were to kill the process (e.g. using Task Manager), you'd find an IOException was thrown instead. Good network code should always be prepared to see an IOException; networks are unreliable and failures do occur. You want to do some reasonable, such as removing the remote endpoint from your connections, rather than just having the whole program crash.

Now, all that said, just because the EndOfStreamException is "normal", that does not mean the code you posted is, or is in any way an example of the right way to do network programming. You have a number of issues:

There is no explicit graceful closure.

Network I/O provides a normal way to close connections, which involves handshaking on both endpoints to indicate when they are done sending, and when they are done receiving. One endpoint will indicate it's done sending; the other will note this (using the 0-byte-read mentioned above) and then itself indicate it's done both sending and receiving.

TcpClient and NetworkStream don't expose this directly, but you can use the TcpClient.Client property to get the Socket object to do a better graceful closure, i.e. one endpoint can indicate it's done sending, and still be able to wait until the other endpoint is also done sending.

Using the TcpClient.Close() method to disconnect is like hanging up the phone on someone without saying "good-bye". Using Socket.Shutdown() is like finishing a phone call with a polite "okay, that's everything I wanted to say…was there anything else?"

You are using BinaryReader but not handling the EndOfStreamException correctly.

Your client uses two connections to communicate with the server.

Network I/O uses the Socket object, which supports full-duplex communications. There is no need to create a second connection just to do both reading and writing. A single connection suffices, and is better because when you split the send and receive into two connections, then you also need to add something to your protocol so that the server knows those two connections represent a single client (which your code does not actually do).

A client is not removed from server list when it disconnected (you noted this in your question).

The client list is not thread-safe.

Your Chat() method has an extra "while (true)" in it.

I have modified your original example to address all of the above, which I've presented here:

Server Program.cs:

```<code>class Program
{
    private static readonly object _lock = new object();
    private static readonly List<TcpClient> clients = new List<TcpClient>();

    public static TcpClient[] GetClients()
    {
        lock (_lock) return clients.ToArray();
    }

    public static int GetClientCount()
    {
        lock (_lock) return clients.Count;
    }

    public static void RemoveClient(TcpClient client)
    {
        lock (_lock) clients.Remove(client);
    }

    static void Main(string[] args)
    {
        IPAddress ip = IPAddress.Parse("127.0.0.1");
        TcpListener ServerSocket = new TcpListener(ip, 14000);
        ServerSocket.Start();

        Console.WriteLine("Server started.");
        while (true)
        {
            TcpClient clientSocket = ServerSocket.AcceptTcpClient();
            Console.WriteLine($"client connected: {clientSocket.Client.RemoteEndPoint}");
            lock (_lock) clients.Add(clientSocket);
            handleClient client = new handleClient();
            client.startClient(clientSocket);

            Console.WriteLine($"{GetClientCount()} clients connected");
        }
    }
}
</code>```

Server handleClient.cs:

```<code>public class handleClient
{
    TcpClient clientSocket;

    public void startClient(TcpClient inClientSocket)
    {
        this.clientSocket = inClientSocket;
        Thread ctThread = new Thread(Chat);
        ctThread.Start();
    }

    private void Chat()
    {
        BinaryReader reader = new BinaryReader(clientSocket.GetStream());

        try
        {
            while (true)
            {
                string message = reader.ReadString();
                foreach (var client in Program.GetClients())
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(message);
                }
            }
        }
        catch (EndOfStreamException)
        {
            Console.WriteLine($"client disconnecting: {clientSocket.Client.RemoteEndPoint}");
            clientSocket.Client.Shutdown(SocketShutdown.Both);
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException reading from {clientSocket.Client.RemoteEndPoint}: {e.Message}");
        }

        clientSocket.Close();
        Program.RemoveClient(clientSocket);
        Console.WriteLine($"{Program.GetClientCount()} clients connected");
    }
}
</code>```

Client Program.cs:

```<code>class Program
{
    private static readonly object _lock = new object();
    private static bool _closed;

    public static void Write(TcpClient client)
    {
        try
        {
            string str;
            SocketShutdown reason = SocketShutdown.Send;

            while ((str = Console.ReadLine()) != "")
            {
                lock (_lock)
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(str);

                    if (_closed)
                    {
                        // Remote endpoint already said they are done sending,
                        // so we're done with both sending and receiving.
                        reason = SocketShutdown.Both;
                        break;
                    }
                }
            }

            client.Client.Shutdown(reason);
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException writing to socket: {e.Message}");
        }
    }

    public static void Read(TcpClient client)
    {
        try
        {
            while (true)
            {
                try
                {
                    BinaryReader reader = new BinaryReader(client.GetStream());
                    Console.WriteLine(reader.ReadString());
                }
                catch (EndOfStreamException)
                {
                    lock (_lock)
                    {
                        _closed = true;
                        return;
                    }
                }
            }
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException reading from socket: {e.Message}");
        }
    }

    static void Main(string[] args)
    {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        Thread writeThread = new Thread(() => Write(client));
        Thread readThread = new Thread(() => Read(client));
        writeThread.Start();
        readThread.Start();

        writeThread.Join();
        readThread.Join();

        client.Close();
        Console.WriteLine("client exiting");
    }
}
</code>```

Note that I did not, for the most part, address the inconsistent and unconventional naming you've used in your code. The only exception was for the thread variables in the client code, because I really don't like capitalized local variables that exactly match the name of a type.

You have some other problems as well, which the above revision of your code does not address. These include:

You're using BinaryReader. This is in a lot of ways an annoying class to use. I recommend, especially for a chat-server scenario where you're only dealing with text anyway, that you switch to using StreamReader/StreamWriter.

There is improper coupling/separation of concerns. Your Program class has server code, and the server code knows about the Program class. It would be much better to encapsulate both the server and client implementations into their own classes, separate from the main entry-point of the program, and to further decouple the top-level server code with the per-client data structure (use C#'s event to allow the top-level server code to be notified of important events, such as the need to remove a client from the list, without having the per-client data structure have to actually know about the top-level server object, never mind its client list).

You should provide a mechanism to gracefully shutdown server.

Normally, I would say that these are outside the scope of an answer like this, which is already quite long. I've addressed the immediate concern in your code and then some, and that is nominally sufficient.

However, I've been meaning to write an updated version of the basic network programming example I'd written some years ago, as a sort of "intermediate" example, adding multiple client support, asynchronous operation, and using the latest C# features (like async/await). So, I went ahead and took some time to do that. I guess I'll post it to my blog eventually…that's a whole other project. In the meantime, here's that code (note that this is an entirely from-scratch example…it made more sense to do that than to try to rework the code you had)…

Most of the grunt work for this implementation is in a single class shared by the server and client:

```<code>/// <summary>
/// Represents a remote end-point for the chat server and clients
/// </summary>
public sealed class ConnectedEndPoint : IDisposable
{
    private readonly object _lock = new object();
    private readonly Socket _socket;
    private readonly StreamReader _reader;
    private readonly StreamWriter _writer;
    private bool _closing;

    /// <summary>
    /// Gets the address of the connected remote end-point
    /// </summary>
    public IPEndPoint RemoteEndPoint { get { return (IPEndPoint)_socket.RemoteEndPoint; } }

    /// <summary>
    /// Gets a <see cref="Task"/> representing the on-going read operation of the connection
    /// </summary>
    public Task ReadTask { get; }

    /// <summary>
    /// Connect to an existing remote end-point (server) and return the
    /// <see cref="ConnectedEndPoint"/> object representing the new connection
    /// </summary>
    /// <param name="remoteEndPoint">The address of the remote end-point to connect to</param>
    /// <param name="readCallback">The callback which will be called when a line of text is read from the newly-created connection</param>
    /// <returns></returns>
    public static ConnectedEndPoint Connect(IPEndPoint remoteEndPoint, Action<ConnectedEndPoint, string> readCallback)
    {
        Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

        socket.Connect(remoteEndPoint);

        return new ConnectedEndPoint(socket, readCallback);
    }

    /// <summary>
    /// Asynchronously accept a new connection from a remote end-point
    /// </summary>
    /// <param name="listener">The listening <see cref="Socket"/> which will accept the connection</param>
    /// <param name="readCallback">The callback which will be called when a line of text is read from the newly-created connection</param>
    /// <returns></returns>
    public static async Task<ConnectedEndPoint> AcceptAsync(Socket listener, Action<ConnectedEndPoint, string> readCallback)
    {
        Socket clientSocket = await Task.Factory.FromAsync(listener.BeginAccept, listener.EndAccept, null);

        return new ConnectedEndPoint(clientSocket, readCallback);
    }

    /// <summary>
    /// Write a line of text to the connection, sending it to the remote end-point
    /// </summary>
    /// <param name="text">The line of text to write</param>
    public void WriteLine(string text)
    {
        lock (_lock)
        {
            if (!_closing)
            {
                _writer.WriteLine(text);
                _writer.Flush();
            }
        }
    }

    /// <summary>
    /// Initiates a graceful closure of the connection
    /// </summary>
    public void Shutdown()
    {
        _Shutdown(SocketShutdown.Send);
    }

    /// <summary>
    /// Implements <see cref="IDisposable.Dispose"/>
    /// </summary>
    public void Dispose()
    {
        _reader.Dispose();
        _writer.Dispose();
        _socket.Close();
    }

    /// <summary>
    /// Constructor. Private -- use one of the factory methods to create new connections.
    /// </summary>
    /// <param name="socket">The <see cref="Socket"/> for the new connection</param>
    /// <param name="readCallback">The callback for reading lines on the new connection</param>
    private ConnectedEndPoint(Socket socket, Action<ConnectedEndPoint, string> readCallback)
    {
        _socket = socket;
        Stream stream = new NetworkStream(_socket);
        _reader = new StreamReader(stream, Encoding.UTF8, false, 1024, true);
        _writer = new StreamWriter(stream, Encoding.UTF8, 1024, true);

        ReadTask = _ConsumeSocketAsync(readCallback);
    }

    private void _Shutdown(SocketShutdown reason)
    {
        lock (_lock)
        {
            if (!_closing)
            {
                _socket.Shutdown(reason);
                _closing = true;
            }
        }
    }

    private async Task _ConsumeSocketAsync(Action<ConnectedEndPoint, string> callback)
    {
        string line;

        while ((line = await _reader.ReadLineAsync()) != null)
        {
            callback(this, line);
        }

        _Shutdown(SocketShutdown.Both);
    }
}
</code>```

A client program would use that class directly. The server side is encapsulated in another class, found in the same DLL with the above:

```<code>/// <summary>
/// Event arguments for the <see cref="ChatServer.Status"/> event
/// </summary>
public class StatusEventArgs : EventArgs
{
    /// <summary>
    /// Gets the status text
    /// </summary>
    public string StatusText { get; }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="statusText">The status text</param>
    public StatusEventArgs(string statusText)
    {
        StatusText = statusText;
    }
}

/// <summary>
/// A server implementing a simple line-based chat server
/// </summary>
public class ChatServer
{
    private readonly object _lock = new object();
    private readonly Socket _listener;
    private readonly List<ConnectedEndPoint> _clients = new List<ConnectedEndPoint>();
    private bool _closing;

    /// <summary>
    /// Gets a task representing the listening state of the servdere
    /// </summary>
    public Task ListenTask { get; }

    /// <summary>
    /// Raised when the server has status to report
    /// </summary>
    public event EventHandler<StatusEventArgs> Status;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="port">The port number the server should listen on</param>
    public ChatServer(int port)
    {
        _listener = new Socket(SocketType.Stream, ProtocolType.Tcp);
        _listener.Bind(new IPEndPoint(IPAddress.Any, port));
        _listener.Listen(int.MaxValue);
        ListenTask = _ListenAsync();
    }

    /// <summary>
    /// Initiates a shutdown of the chat server.
    /// </summary>
    /// <remarks>This method closes the listening socket, which will subsequently
    /// cause the listening task to inform any connected clients that the server
    /// is shutting down, and to wait for the connected clients to finish a graceful
    /// closure of their connections.
    /// </remarks>
    public void Shutdown()
    {
        _listener.Close();
    }

    private async Task _ListenAsync()
    {
        try
        {
            while (true)
            {
                ConnectedEndPoint client = await ConnectedEndPoint.AcceptAsync(_listener, _ClientReadLine);

                _AddClient(client);
                _CleanupClientAsync(client);
            }
        }
        catch (ObjectDisposedException)
        {
            _OnStatus("Server's listening socket closed");
        }
        catch (IOException e)
        {
            _OnStatus($"Listening socket IOException: {e.Message}");
        }

        await _CleanupServerAsync();
    }

    private async Task _CleanupServerAsync()
    {
        ConnectedEndPoint[] clients;

        lock (_lock)
        {
            _closing = true;
            clients = _clients.ToArray();
        }

        foreach (ConnectedEndPoint client in clients)
        {
            try
            {
                client.WriteLine("Chat server is shutting down");
            }
            catch (IOException e)
            {
                _OnClientException(client, e.Message);
            }
            client.Shutdown();
        }

        // Clients are expected to participate in graceful closure. If they do,
        // this will complete when all clients have acknowledged the shutdown.
        // In a real-world program, may be a good idea to include a timeout in
        // case of network issues or misbehaving/crashed clients. Implementing
        // the timeout is beyond the scope of this proof-of-concept demo code.
        try
        {
            await Task.WhenAll(clients.Select(c => c.ReadTask));
        }
        catch (AggregateException)
        {
            // Actual exception for each client will have already
            // been reported by _CleanupClientAsync()
        }
    }

    // Top-level "clean-up" method, which will observe and report all exceptions
    // In real-world code, would probably want to simply log any unexpected exceptions
    // to a log file and then exit the process. Here, we just exit after reporting
    // exception info to caller. In either case, there's no need to observe a Task from
    // this method, and async void simplifies the call (no need to receive and then ignore
    // the Task object just to keep the compiler quiet).
    private async void _CleanupClientAsync(ConnectedEndPoint client)
    {
        try
        {
            await client.ReadTask;
        }
        catch (IOException e)
        {
            _OnClientException(client, e.Message);
        }
        catch (Exception e)
        {
            // Unexpected exceptions are programmer-error. They could be anything, and leave
            // the program in an unknown, possibly corrupt state. The only reasonable disposition
            // is to log, then exit.
            //
            // Full stack-trace, because who knows what this exception was. Will need the
            // stack-trace to do any diagnostic work.
            _OnStatus($"Unexpected client connection exception. {e}");
            Environment.Exit(1);
        }
        finally
        {
            _RemoveClient(client);
            client.Dispose();
        }
    }

    private void _ClientReadLine(ConnectedEndPoint readClient, string text)
    {
        _OnStatus($"Client {readClient.RemoteEndPoint}: \"{text}\"");

        lock (_lock)
        {
            if (_closing)
            {
                return;
            }

            text = $"{readClient.RemoteEndPoint}: {text}";

            foreach (ConnectedEndPoint client in _clients.Where(c => c != readClient))
            {
                try
                {
                    client.WriteLine(text);
                }
                catch (IOException e)
                {
                    _OnClientException(client, e.Message);
                }
            }
        }
    }

    private void _AddClient(ConnectedEndPoint client)
    {
        lock (_lock)
        {
            _clients.Add(client);
            _OnStatus($"added client {client.RemoteEndPoint} -- {_clients.Count} clients connected");
        }
    }

    private void _RemoveClient(ConnectedEndPoint client)
    {
        lock (_lock)
        {
            _clients.Remove(client);
            _OnStatus($"removed client {client.RemoteEndPoint} -- {_clients.Count} clients connected");
        }
    }

    private void _OnStatus(string statusText)
    {
        Status?.Invoke(this, new StatusEventArgs(statusText));
    }

    private void _OnClientException(ConnectedEndPoint client, string message)
    {
        _OnStatus($"Client {client.RemoteEndPoint} IOException: {message}");
    }
}
</code>```

And that is, for the most part, all you need. The DLL code above is referenced (in my example) by two different programs, a server and a client.

Here's the server:

```<code>class Program
{
    private const int _kportNumber = 5678;

    static void Main(string[] args)
    {
        ChatServer server = new ChatServer(_kportNumber);

        server.Status += (s, e) => WriteLine(e.StatusText);

        Task serverTask = _WaitForServer(server);

        WriteLine("Press return to shutdown server...");
        ReadLine();

        server.Shutdown();
        serverTask.Wait();
    }

    private static async Task _WaitForServer(ChatServer server)
    {
        try
        {
            await server.ListenTask;
        }
        catch (Exception e)
        {
            WriteLine($"Server exception: {e}");
        }
    }
}
</code>```

And here's the client:

```<code>class Program
{
    private const int _kportNumber = 5678;

    static void Main(string[] args)
    {
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Loopback, _kportNumber);
        ConnectedEndPoint server = ConnectedEndPoint.Connect(remoteEndPoint, (c, s) => WriteLine(s));

        _StartUserInput(server);
        _SafeWaitOnServerRead(server).Wait();
    }

    private static void _StartUserInput(ConnectedEndPoint server)
    {
        // Get user input in a new thread, so main thread can handle waiting
        // on connection.
        new Thread(() =>
        {
            try
            {
                string line;

                while ((line = ReadLine()) != "")
                {
                    server.WriteLine(line);
                }

                server.Shutdown();
            }
            catch (IOException e)
            {
                WriteLine($"Server {server.RemoteEndPoint} IOException: {e.Message}");
            }
            catch (Exception e)
            {
                WriteLine($"Unexpected server exception: {e}");
                Environment.Exit(1);
            }
        })
        {
            // Setting IsBackground means this thread won't keep the
            // process alive. So, if the connection is closed by the server,
            // the main thread can exit and the process as a whole will still
            // be able to exit.
            IsBackground = true
        }.Start();
    }

    private static async Task _SafeWaitOnServerRead(ConnectedEndPoint server)
    {
        try
        {
            await server.ReadTask;
        }
        catch (IOException e)
        {
            WriteLine($"Server {server.RemoteEndPoint} IOException: {e.Message}");
        }
        catch (Exception e)
        {
            // Should never happen. It's a bug in this code if it does.
            WriteLine($"Unexpected server exception: {e}");
        }
    }
}
</code>```

In my opinion, one of the most important things for you to note in the above is that the ConnectedEndPoint and ChatServer classes have zero dependency on the classes which use them. Through the use of callback delegates and events, the code that depends on these classes are able to interact bi-directionally without these supporting classes having to know about the types that code resides in (see "inversion of control", which this is a variation of).

The more you can make your code relationships look like a tree with only single-direction references, the easier it will be to write the code, and to maintain it later.

Note: I used both events and callback delegates for the sake of illustration. Either approach works fine on its own. The main trade-offs are complexity vs. flexibility. Using events makes the code more flexible — event handlers can be added and removed as necessary — but if one implements events using the .NET convention of a method signature with a sender and an EventArgs parameter, it is somewhat more "heavy-weight" than just passing a simple callback delegate when creating the object in question. I put an example of each in the code, and you can decide which approaches you prefer in which situations.

You'll also note that the above makes heavy use of C#'s asynchronous features. At first, this may make the code seem harder to read. But in fact, it's actually much easier to get everything working using these features, than if I were to try to use the older BeginXXX()/EndXXX() methods or, heaven forbid, dedicate a single thread to each connection (which scales very poorly as the client count goes up). It's absolutely worth getting used to thinking of operations which are inherently asynchronous, such as network I/O, in this way.

Body:
I'm looking for a way to handle a disconnect, because every time I close a client, the server stops working. I get an error message, that it is "unable to read beyond the end of the stream" in this line:

string message = reader.ReadString();

Also I need a way to delet the disconnected client from the clients list.
Here is my code:
Server

using System;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Collections.Generic;

namespace Server
{
    class Server
    {
    public static List<TcpClient> clients = new List<TcpClient>();

    static void Main(string[] args)
    {
        IPAddress ip = IPAddress.Parse("127.0.0.1");
        TcpListener ServerSocket = new TcpListener(ip, 14000);
        ServerSocket.Start();

        Console.WriteLine("Server started.");
        while (true)
        {
            TcpClient clientSocket = ServerSocket.AcceptTcpClient();
            clients.Add(clientSocket);
            handleClient client = new handleClient();
            client.startClient(clientSocket);
        }
    }
}

public class handleClient
{
    TcpClient clientSocket;
    public void startClient(TcpClient inClientSocket)
    {
        this.clientSocket = inClientSocket;
        Thread ctThread = new Thread(Chat);
        ctThread.Start();
    }

    private void Chat()
    {
        while (true)
        {
            BinaryReader reader = new BinaryReader(clientSocket.GetStream());
            while (true)
            {
                string message = reader.ReadString();
                foreach (var client in Server.clients)
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(message);
                }
            }
        }
    }
}
}

Client

using System;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Client
{
   class Client
   {
       public static void Write()
       {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        while (true)
        {
            string str = Console.ReadLine();
            BinaryWriter writer = new BinaryWriter(client.GetStream());
            writer.Write(str);
        }
    }

    public static void Read()
    {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        while (true)
        {
            BinaryReader reader = new BinaryReader(client.GetStream());
            Console.WriteLine(reader.ReadString());
        }
    }

    static void Main(string[] args)
    {
        Thread Thread = new Thread(Write);
        Thread Thread2 = new Thread(Read);
        Thread.Start();
        Thread2.Start();
    }
}
}

Body:
every time I close a client, the server stops working. I get an error message, that it is "unable to read beyond the end of the stream"

This is, in some sense, completely normal. That is, when using BinaryReader, its normal behavior is to throw EndOfStreamException when reaching the end-of-stream.

Why did it reach end-of-stream? Well, because the client disconnected and that's what happens to the stream. At the socket level, what really happens is that a read operation completes with 0 as the count of bytes read. This is the indication that the client has gracefully closed the socket and will not be sending any more data.

In the .NET API, this is translated to the end of the NetworkStream that TcpClient uses to wrap the Socket object that's actually handling the network I/O. And this NetworkStream object is in turn being wrapped by your BinaryReader object. And BinaryReader throws that exception when it reaches the end of the stream.

Note that your code does not actually provide a graceful way for the user to close a client. They will have to use Ctrl+C, or kill the process outright. Using the former has the serendipitous effect of performing a graceful shutdown of the socket, but only because .NET is handling the termination of the process and runs finalizers on your objects, such as the TcpClient object used to connect to the server, and the finalizer calls Socket.Shutdown() to tell the server it's closing.

If you were to kill the process (e.g. using Task Manager), you'd find an IOException was thrown instead. Good network code should always be prepared to see an IOException; networks are unreliable and failures do occur. You want to do some reasonable, such as removing the remote endpoint from your connections, rather than just having the whole program crash.

Now, all that said, just because the EndOfStreamException is "normal", that does not mean the code you posted is, or is in any way an example of the right way to do network programming. You have a number of issues:

There is no explicit graceful closure.

Network I/O provides a normal way to close connections, which involves handshaking on both endpoints to indicate when they are done sending, and when they are done receiving. One endpoint will indicate it's done sending; the other will note this (using the 0-byte-read mentioned above) and then itself indicate it's done both sending and receiving.

TcpClient and NetworkStream don't expose this directly, but you can use the TcpClient.Client property to get the Socket object to do a better graceful closure, i.e. one endpoint can indicate it's done sending, and still be able to wait until the other endpoint is also done sending.

Using the TcpClient.Close() method to disconnect is like hanging up the phone on someone without saying "good-bye". Using Socket.Shutdown() is like finishing a phone call with a polite "okay, that's everything I wanted to say…was there anything else?"

You are using BinaryReader but not handling the EndOfStreamException correctly.

Your client uses two connections to communicate with the server.

Network I/O uses the Socket object, which supports full-duplex communications. There is no need to create a second connection just to do both reading and writing. A single connection suffices, and is better because when you split the send and receive into two connections, then you also need to add something to your protocol so that the server knows those two connections represent a single client (which your code does not actually do).

A client is not removed from server list when it disconnected (you noted this in your question).

The client list is not thread-safe.

Your Chat() method has an extra "while (true)" in it.

I have modified your original example to address all of the above, which I've presented here:

Server Program.cs:

class Program
{
    private static readonly object _lock = new object();
    private static readonly List<TcpClient> clients = new List<TcpClient>();

    public static TcpClient[] GetClients()
    {
        lock (_lock) return clients.ToArray();
    }

    public static int GetClientCount()
    {
        lock (_lock) return clients.Count;
    }

    public static void RemoveClient(TcpClient client)
    {
        lock (_lock) clients.Remove(client);
    }

    static void Main(string[] args)
    {
        IPAddress ip = IPAddress.Parse("127.0.0.1");
        TcpListener ServerSocket = new TcpListener(ip, 14000);
        ServerSocket.Start();

        Console.WriteLine("Server started.");
        while (true)
        {
            TcpClient clientSocket = ServerSocket.AcceptTcpClient();
            Console.WriteLine($"client connected: {clientSocket.Client.RemoteEndPoint}");
            lock (_lock) clients.Add(clientSocket);
            handleClient client = new handleClient();
            client.startClient(clientSocket);

            Console.WriteLine($"{GetClientCount()} clients connected");
        }
    }
}

Server handleClient.cs:

public class handleClient
{
    TcpClient clientSocket;

    public void startClient(TcpClient inClientSocket)
    {
        this.clientSocket = inClientSocket;
        Thread ctThread = new Thread(Chat);
        ctThread.Start();
    }

    private void Chat()
    {
        BinaryReader reader = new BinaryReader(clientSocket.GetStream());

        try
        {
            while (true)
            {
                string message = reader.ReadString();
                foreach (var client in Program.GetClients())
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(message);
                }
            }
        }
        catch (EndOfStreamException)
        {
            Console.WriteLine($"client disconnecting: {clientSocket.Client.RemoteEndPoint}");
            clientSocket.Client.Shutdown(SocketShutdown.Both);
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException reading from {clientSocket.Client.RemoteEndPoint}: {e.Message}");
        }

        clientSocket.Close();
        Program.RemoveClient(clientSocket);
        Console.WriteLine($"{Program.GetClientCount()} clients connected");
    }
}

Client Program.cs:

class Program
{
    private static readonly object _lock = new object();
    private static bool _closed;

    public static void Write(TcpClient client)
    {
        try
        {
            string str;
            SocketShutdown reason = SocketShutdown.Send;

            while ((str = Console.ReadLine()) != "")
            {
                lock (_lock)
                {
                    BinaryWriter writer = new BinaryWriter(client.GetStream());
                    writer.Write(str);

                    if (_closed)
                    {
                        // Remote endpoint already said they are done sending,
                        // so we're done with both sending and receiving.
                        reason = SocketShutdown.Both;
                        break;
                    }
                }
            }

            client.Client.Shutdown(reason);
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException writing to socket: {e.Message}");
        }
    }

    public static void Read(TcpClient client)
    {
        try
        {
            while (true)
            {
                try
                {
                    BinaryReader reader = new BinaryReader(client.GetStream());
                    Console.WriteLine(reader.ReadString());
                }
                catch (EndOfStreamException)
                {
                    lock (_lock)
                    {
                        _closed = true;
                        return;
                    }
                }
            }
        }
        catch (IOException e)
        {
            Console.WriteLine($"IOException reading from socket: {e.Message}");
        }
    }

    static void Main(string[] args)
    {
        TcpClient client = new TcpClient("127.0.0.1", 14000);
        Thread writeThread = new Thread(() => Write(client));
        Thread readThread = new Thread(() => Read(client));
        writeThread.Start();
        readThread.Start();

        writeThread.Join();
        readThread.Join();

        client.Close();
        Console.WriteLine("client exiting");
    }
}

Note that I did not, for the most part, address the inconsistent and unconventional naming you've used in your code. The only exception was for the thread variables in the client code, because I really don't like capitalized local variables that exactly match the name of a type.

You have some other problems as well, which the above revision of your code does not address. These include:

You're using BinaryReader. This is in a lot of ways an annoying class to use. I recommend, especially for a chat-server scenario where you're only dealing with text anyway, that you switch to using StreamReader/StreamWriter.

There is improper coupling/separation of concerns. Your Program class has server code, and the server code knows about the Program class. It would be much better to encapsulate both the server and client implementations into their own classes, separate from the main entry-point of the program, and to further decouple the top-level server code with the per-client data structure (use C#'s event to allow the top-level server code to be notified of important events, such as the need to remove a client from the list, without having the per-client data structure have to actually know about the top-level server object, never mind its client list).

You should provide a mechanism to gracefully shutdown server.

Normally, I would say that these are outside the scope of an answer like this, which is already quite long. I've addressed the immediate concern in your code and then some, and that is nominally sufficient.

However, I've been meaning to write an updated version of the basic network programming example I'd written some years ago, as a sort of "intermediate" example, adding multiple client support, asynchronous operation, and using the latest C# features (like async/await). So, I went ahead and took some time to do that. I guess I'll post it to my blog eventually…that's a whole other project. In the meantime, here's that code (note that this is an entirely from-scratch example…it made more sense to do that than to try to rework the code you had)…

Most of the grunt work for this implementation is in a single class shared by the server and client:

/// <summary>
/// Represents a remote end-point for the chat server and clients
/// </summary>
public sealed class ConnectedEndPoint : IDisposable
{
    private readonly object _lock = new object();
    private readonly Socket _socket;
    private readonly StreamReader _reader;
    private readonly StreamWriter _writer;
    private bool _closing;

    /// <summary>
    /// Gets the address of the connected remote end-point
    /// </summary>
    public IPEndPoint RemoteEndPoint { get { return (IPEndPoint)_socket.RemoteEndPoint; } }

    /// <summary>
    /// Gets a <see cref="Task"/> representing the on-going read operation of the connection
    /// </summary>
    public Task ReadTask { get; }

    /// <summary>
    /// Connect to an existing remote end-point (server) and return the
    /// <see cref="ConnectedEndPoint"/> object representing the new connection
    /// </summary>
    /// <param name="remoteEndPoint">The address of the remote end-point to connect to</param>
    /// <param name="readCallback">The callback which will be called when a line of text is read from the newly-created connection</param>
    /// <returns></returns>
    public static ConnectedEndPoint Connect(IPEndPoint remoteEndPoint, Action<ConnectedEndPoint, string> readCallback)
    {
        Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

        socket.Connect(remoteEndPoint);

        return new ConnectedEndPoint(socket, readCallback);
    }

    /// <summary>
    /// Asynchronously accept a new connection from a remote end-point
    /// </summary>
    /// <param name="listener">The listening <see cref="Socket"/> which will accept the connection</param>
    /// <param name="readCallback">The callback which will be called when a line of text is read from the newly-created connection</param>
    /// <returns></returns>
    public static async Task<ConnectedEndPoint> AcceptAsync(Socket listener, Action<ConnectedEndPoint, string> readCallback)
    {
        Socket clientSocket = await Task.Factory.FromAsync(listener.BeginAccept, listener.EndAccept, null);

        return new ConnectedEndPoint(clientSocket, readCallback);
    }

    /// <summary>
    /// Write a line of text to the connection, sending it to the remote end-point
    /// </summary>
    /// <param name="text">The line of text to write</param>
    public void WriteLine(string text)
    {
        lock (_lock)
        {
            if (!_closing)
            {
                _writer.WriteLine(text);
                _writer.Flush();
            }
        }
    }

    /// <summary>
    /// Initiates a graceful closure of the connection
    /// </summary>
    public void Shutdown()
    {
        _Shutdown(SocketShutdown.Send);
    }

    /// <summary>
    /// Implements <see cref="IDisposable.Dispose"/>
    /// </summary>
    public void Dispose()
    {
        _reader.Dispose();
        _writer.Dispose();
        _socket.Close();
    }

    /// <summary>
    /// Constructor. Private -- use one of the factory methods to create new connections.
    /// </summary>
    /// <param name="socket">The <see cref="Socket"/> for the new connection</param>
    /// <param name="readCallback">The callback for reading lines on the new connection</param>
    private ConnectedEndPoint(Socket socket, Action<ConnectedEndPoint, string> readCallback)
    {
        _socket = socket;
        Stream stream = new NetworkStream(_socket);
        _reader = new StreamReader(stream, Encoding.UTF8, false, 1024, true);
        _writer = new StreamWriter(stream, Encoding.UTF8, 1024, true);

        ReadTask = _ConsumeSocketAsync(readCallback);
    }

    private void _Shutdown(SocketShutdown reason)
    {
        lock (_lock)
        {
            if (!_closing)
            {
                _socket.Shutdown(reason);
                _closing = true;
            }
        }
    }

    private async Task _ConsumeSocketAsync(Action<ConnectedEndPoint, string> callback)
    {
        string line;

        while ((line = await _reader.ReadLineAsync()) != null)
        {
            callback(this, line);
        }

        _Shutdown(SocketShutdown.Both);
    }
}

A client program would use that class directly. The server side is encapsulated in another class, found in the same DLL with the above:

/// <summary>
/// Event arguments for the <see cref="ChatServer.Status"/> event
/// </summary>
public class StatusEventArgs : EventArgs
{
    /// <summary>
    /// Gets the status text
    /// </summary>
    public string StatusText { get; }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="statusText">The status text</param>
    public StatusEventArgs(string statusText)
    {
        StatusText = statusText;
    }
}

/// <summary>
/// A server implementing a simple line-based chat server
/// </summary>
public class ChatServer
{
    private readonly object _lock = new object();
    private readonly Socket _listener;
    private readonly List<ConnectedEndPoint> _clients = new List<ConnectedEndPoint>();
    private bool _closing;

    /// <summary>
    /// Gets a task representing the listening state of the servdere
    /// </summary>
    public Task ListenTask { get; }

    /// <summary>
    /// Raised when the server has status to report
    /// </summary>
    public event EventHandler<StatusEventArgs> Status;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="port">The port number the server should listen on</param>
    public ChatServer(int port)
    {
        _listener = new Socket(SocketType.Stream, ProtocolType.Tcp);
        _listener.Bind(new IPEndPoint(IPAddress.Any, port));
        _listener.Listen(int.MaxValue);
        ListenTask = _ListenAsync();
    }

    /// <summary>
    /// Initiates a shutdown of the chat server.
    /// </summary>
    /// <remarks>This method closes the listening socket, which will subsequently
    /// cause the listening task to inform any connected clients that the server
    /// is shutting down, and to wait for the connected clients to finish a graceful
    /// closure of their connections.
    /// </remarks>
    public void Shutdown()
    {
        _listener.Close();
    }

    private async Task _ListenAsync()
    {
        try
        {
            while (true)
            {
                ConnectedEndPoint client = await ConnectedEndPoint.AcceptAsync(_listener, _ClientReadLine);

                _AddClient(client);
                _CleanupClientAsync(client);
            }
        }
        catch (ObjectDisposedException)
        {
            _OnStatus("Server's listening socket closed");
        }
        catch (IOException e)
        {
            _OnStatus($"Listening socket IOException: {e.Message}");
        }

        await _CleanupServerAsync();
    }

    private async Task _CleanupServerAsync()
    {
        ConnectedEndPoint[] clients;

        lock (_lock)
        {
            _closing = true;
            clients = _clients.ToArray();
        }

        foreach (ConnectedEndPoint client in clients)
        {
            try
            {
                client.WriteLine("Chat server is shutting down");
            }
            catch (IOException e)
            {
                _OnClientException(client, e.Message);
            }
            client.Shutdown();
        }

        // Clients are expected to participate in graceful closure. If they do,
        // this will complete when all clients have acknowledged the shutdown.
        // In a real-world program, may be a good idea to include a timeout in
        // case of network issues or misbehaving/crashed clients. Implementing
        // the timeout is beyond the scope of this proof-of-concept demo code.
        try
        {
            await Task.WhenAll(clients.Select(c => c.ReadTask));
        }
        catch (AggregateException)
        {
            // Actual exception for each client will have already
            // been reported by _CleanupClientAsync()
        }
    }

    // Top-level "clean-up" method, which will observe and report all exceptions
    // In real-world code, would probably want to simply log any unexpected exceptions
    // to a log file and then exit the process. Here, we just exit after reporting
    // exception info to caller. In either case, there's no need to observe a Task from
    // this method, and async void simplifies the call (no need to receive and then ignore
    // the Task object just to keep the compiler quiet).
    private async void _CleanupClientAsync(ConnectedEndPoint client)
    {
        try
        {
            await client.ReadTask;
        }
        catch (IOException e)
        {
            _OnClientException(client, e.Message);
        }
        catch (Exception e)
        {
            // Unexpected exceptions are programmer-error. They could be anything, and leave
            // the program in an unknown, possibly corrupt state. The only reasonable disposition
            // is to log, then exit.
            //
            // Full stack-trace, because who knows what this exception was. Will need the
            // stack-trace to do any diagnostic work.
            _OnStatus($"Unexpected client connection exception. {e}");
            Environment.Exit(1);
        }
        finally
        {
            _RemoveClient(client);
            client.Dispose();
        }
    }

    private void _ClientReadLine(ConnectedEndPoint readClient, string text)
    {
        _OnStatus($"Client {readClient.RemoteEndPoint}: \"{text}\"");

        lock (_lock)
        {
            if (_closing)
            {
                return;
            }

            text = $"{readClient.RemoteEndPoint}: {text}";

            foreach (ConnectedEndPoint client in _clients.Where(c => c != readClient))
            {
                try
                {
                    client.WriteLine(text);
                }
                catch (IOException e)
                {
                    _OnClientException(client, e.Message);
                }
            }
        }
    }

    private void _AddClient(ConnectedEndPoint client)
    {
        lock (_lock)
        {
            _clients.Add(client);
            _OnStatus($"added client {client.RemoteEndPoint} -- {_clients.Count} clients connected");
        }
    }

    private void _RemoveClient(ConnectedEndPoint client)
    {
        lock (_lock)
        {
            _clients.Remove(client);
            _OnStatus($"removed client {client.RemoteEndPoint} -- {_clients.Count} clients connected");
        }
    }

    private void _OnStatus(string statusText)
    {
        Status?.Invoke(this, new StatusEventArgs(statusText));
    }

    private void _OnClientException(ConnectedEndPoint client, string message)
    {
        _OnStatus($"Client {client.RemoteEndPoint} IOException: {message}");
    }
}

And that is, for the most part, all you need. The DLL code above is referenced (in my example) by two different programs, a server and a client.

Here's the server:

class Program
{
    private const int _kportNumber = 5678;

    static void Main(string[] args)
    {
        ChatServer server = new ChatServer(_kportNumber);

        server.Status += (s, e) => WriteLine(e.StatusText);

        Task serverTask = _WaitForServer(server);

        WriteLine("Press return to shutdown server...");
        ReadLine();

        server.Shutdown();
        serverTask.Wait();
    }

    private static async Task _WaitForServer(ChatServer server)
    {
        try
        {
            await server.ListenTask;
        }
        catch (Exception e)
        {
            WriteLine($"Server exception: {e}");
        }
    }
}

And here's the client:

class Program
{
    private const int _kportNumber = 5678;

    static void Main(string[] args)
    {
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Loopback, _kportNumber);
        ConnectedEndPoint server = ConnectedEndPoint.Connect(remoteEndPoint, (c, s) => WriteLine(s));

        _StartUserInput(server);
        _SafeWaitOnServerRead(server).Wait();
    }

    private static void _StartUserInput(ConnectedEndPoint server)
    {
        // Get user input in a new thread, so main thread can handle waiting
        // on connection.
        new Thread(() =>
        {
            try
            {
                string line;

                while ((line = ReadLine()) != "")
                {
                    server.WriteLine(line);
                }

                server.Shutdown();
            }
            catch (IOException e)
            {
                WriteLine($"Server {server.RemoteEndPoint} IOException: {e.Message}");
            }
            catch (Exception e)
            {
                WriteLine($"Unexpected server exception: {e}");
                Environment.Exit(1);
            }
        })
        {
            // Setting IsBackground means this thread won't keep the
            // process alive. So, if the connection is closed by the server,
            // the main thread can exit and the process as a whole will still
            // be able to exit.
            IsBackground = true
        }.Start();
    }

    private static async Task _SafeWaitOnServerRead(ConnectedEndPoint server)
    {
        try
        {
            await server.ReadTask;
        }
        catch (IOException e)
        {
            WriteLine($"Server {server.RemoteEndPoint} IOException: {e.Message}");
        }
        catch (Exception e)
        {
            // Should never happen. It's a bug in this code if it does.
            WriteLine($"Unexpected server exception: {e}");
        }
    }
}

In my opinion, one of the most important things for you to note in the above is that the ConnectedEndPoint and ChatServer classes have zero dependency on the classes which use them. Through the use of callback delegates and events, the code that depends on these classes are able to interact bi-directionally without these supporting classes having to know about the types that code resides in (see "inversion of control", which this is a variation of).

The more you can make your code relationships look like a tree with only single-direction references, the easier it will be to write the code, and to maintain it later.

Note: I used both events and callback delegates for the sake of illustration. Either approach works fine on its own. The main trade-offs are complexity vs. flexibility. Using events makes the code more flexible — event handlers can be added and removed as necessary — but if one implements events using the .NET convention of a method signature with a sender and an EventArgs parameter, it is somewhat more "heavy-weight" than just passing a simple callback delegate when creating the object in question. I put an example of each in the code, and you can decide which approaches you prefer in which situations.

You'll also note that the above makes heavy use of C#'s asynchronous features. At first, this may make the code seem harder to read. But in fact, it's actually much easier to get everything working using these features, than if I were to try to use the older BeginXXX()/EndXXX() methods or, heaven forbid, dedicate a single thread to each connection (which scales very poorly as the client count goes up). It's absolutely worth getting used to thinking of operations which are inherently asynchronous, such as network I/O, in this way.


来源: stackexchange

问:
qsort not working properly with long long
I am sorting a two dimensional array a[n][2], with respect to a[i][0],a[i+1][0] breaking ties with non-decreasing a[i][1],a[i+1][1].
qsort is working fine with integer array but not with long long array.

Integer array code

```<code>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int cmpfunc(const void* a, const void* b)
{
    int x = ((int*)a)[0] - ((int*)b)[0];
    if (x != 0) {
        return x;
    }
    return ((int*)a)[1] - ((int*)b)[1];
}

int main(int argc, char const* argv[])
{
    int n, i, j;
    scanf("%d", &n);
    int a[n][2];
    for (i = 0; i < n; i = i + 1) {
        scanf("%d %d", &a[i][0], &a[i][1]);
    }
    qsort(a, n, sizeof(a[0]), cmpfunc);
    for (i = 0; i < n; i = i + 1) {
        printf("%d %d\n", a[i][0], a[i][1]);
    }
    return 0;
}
</code>```

long long array code

```<code>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int cmpfunc(const void* a, const void* b)
{
    int x = ((int*)a)[0] - ((int*)b)[0];
    if (x != 0) {
        return x;
    }
    return ((int*)a)[1] - ((int*)b)[1];
}

int main(int argc, char const* argv[])
{
    int n, i, j;
    scanf("%d", &n);
    long long a[n][2];
    for (i = 0; i < n; i = i + 1) {
        scanf("%I64d %I64d", &a[i][0], &a[i][1]);
    }
    qsort(a, n, sizeof(a[0]), cmpfunc);
    for (i = 0; i < n; i = i + 1) {
        printf("%I64d %I64d\n", a[i][0], a[i][1]);
    }
    return 0;
}
</code>```

Input:

```<code>5
4 3
4 2
4 1
4 1
4 1
</code>```

Output for first code:

```<code>4 1
4 1
4 1
4 2
4 3
</code>```

Output for second code:

```<code>4 2
4 1
4 1
4 1
4 3
</code>```

答: You still cast to int * in your compare function even though you changed the type of the data to long long.

ContentLicense: CC BY-SA 3.0

Body:
I am sorting a two dimensional array a[n][2], with respect to a[i][0],a[i+1][0] breaking ties with non-decreasing a[i][1],a[i+1][1].
qsort is working fine with integer array but not with long long array.

Integer array code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int cmpfunc(const void* a, const void* b)
{
    int x = ((int*)a)[0] - ((int*)b)[0];
    if (x != 0) {
        return x;
    }
    return ((int*)a)[1] - ((int*)b)[1];
}

int main(int argc, char const* argv[])
{
    int n, i, j;
    scanf("%d", &n);
    int a[n][2];
    for (i = 0; i < n; i = i + 1) {
        scanf("%d %d", &a[i][0], &a[i][1]);
    }
    qsort(a, n, sizeof(a[0]), cmpfunc);
    for (i = 0; i < n; i = i + 1) {
        printf("%d %d\n", a[i][0], a[i][1]);
    }
    return 0;
}

long long array code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

int cmpfunc(const void* a, const void* b)
{
    int x = ((int*)a)[0] - ((int*)b)[0];
    if (x != 0) {
        return x;
    }
    return ((int*)a)[1] - ((int*)b)[1];
}

int main(int argc, char const* argv[])
{
    int n, i, j;
    scanf("%d", &n);
    long long a[n][2];
    for (i = 0; i < n; i = i + 1) {
        scanf("%I64d %I64d", &a[i][0], &a[i][1]);
    }
    qsort(a, n, sizeof(a[0]), cmpfunc);
    for (i = 0; i < n; i = i + 1) {
        printf("%I64d %I64d\n", a[i][0], a[i][1]);
    }
    return 0;
}

Input:

5
4 3
4 2
4 1
4 1
4 1

Output for first code:

4 1
4 1
4 1
4 2
4 3

Output for second code:

4 2
4 1
4 1
4 1
4 3


问:
Apns notifications is not Working with Developement Certificate
Please suggest me, As iam having developement p12 file and dependencies But iam getting Exceptiopn when sending notification through Developement Certificate.p12 file. the Exception is (javax.net.ssl.SSLException) javax.net.ssl.SSLException: Received fatal alert: internal_error</p>

```<code>package com.push.notification.server;

import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.EnhancedApnsNotification;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;

public class ApnsTest {

    private ApnsService service;

    public ApnsTest() {
    try {

        String path = "p12 file name";

        File certFile = new File(path);
        InputStream fis = new FileInputStream(certFile);
        service = APNS.newService().withCert(fis, "pwd")
            .withSandboxDestination()
            .build();
        sendMessage();
    } catch (Exception e) {
        e.printStackTrace();
    }
    }

    public static void main(String[] args) {
    new ApnsTest();
    }

    public void sendMessage() {
    String payload = APNS.newPayload().alertBody("nnnnn").sound("default").build();
    String deviceToken = "267fe9f23984cc6d8ca7b35db3c4b829cdbe2f9f1dbd3258cbbfa8f94e3fd986";
    int now = (int) (new Date().getTime() / 1000);
    EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID(),
        now + 60 * 60, deviceToken, payload);

    System.out.println("Sending push notification");
    try {
        service.push(deviceToken, payload);
    } catch (Exception e) {
        e.printStackTrace();
    }
    }
}
</code>```

答:
Yes, above problem solved by Creating Development certificate once again.

This is procedure enter image description here first in
On your Mac, open Keychain Access

From the top menu, select

Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority…

Fill out your email address, common name
Check Save to disk
Press Continue and save the .certSigningRequest file somewhere
enter image description here

Configuring Push Notifications for the App ID
Once the APP ID registration is completed, you need to configure it to make to work with push notification.
[enter image description here][3]
Select the App ID you just created, and click Edit
At Push Notifications, click Create Certificate then **Continue
Click Choose File… and upload the .certSigningRequest file you have generated and saved on your Mac earlier. Click Generate.
Once the certificate was generated, download it onto your Mac
[enter image description here][4]
1.4 Creating a Private Key
Now you are going to create a private key from the downloaded certificate.
[enter image description here][5]
Double-click the downloaded file. It should open in Keychain Access
Select My Certificates at left. You should find the certificate you just added.
Control-click the certificate, and select Export “Apple Development IOS Push Services:…”…
Save it as ..p12 file, by selecting File Format as Personal Information Exchange (.p12) in the Save As dialog

1.5 Creating a Provisioning Profile on Apple Developer portal,

Go to Provisioning Profiles

Click + to create a new provisioning file

Select iOS App Development, then Continue

Select a correct App ID from the drop-down list, then Continue

Select a correct certificate from the list, then Continue

Select devices you are going to develop with, the Continue

Enter a name for the provisioning profile, then Generate

Download the file

Double-click open the file in Xcode. The profile now should be added to Xcode.

Body:
Please suggest me, As iam having developement p12 file and dependencies But iam getting Exceptiopn when sending notification through Developement Certificate.p12 file. the Exception is (javax.net.ssl.SSLException) javax.net.ssl.SSLException: Received fatal alert: internal_error

package com.push.notification.server;

import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.EnhancedApnsNotification;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Date;

public class ApnsTest {

    private ApnsService service;

    public ApnsTest() {
    try {

        String path = "p12 file name";

        File certFile = new File(path);
        InputStream fis = new FileInputStream(certFile);
        service = APNS.newService().withCert(fis, "pwd")
            .withSandboxDestination()
            .build();
        sendMessage();
    } catch (Exception e) {
        e.printStackTrace();
    }
    }

    public static void main(String[] args) {
    new ApnsTest();
    }

    public void sendMessage() {
    String payload = APNS.newPayload().alertBody("nnnnn").sound("default").build();
    String deviceToken = "267fe9f23984cc6d8ca7b35db3c4b829cdbe2f9f1dbd3258cbbfa8f94e3fd986";
    int now = (int) (new Date().getTime() / 1000);
    EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID(),
        now + 60 * 60, deviceToken, payload);

    System.out.println("Sending push notification");
    try {
        service.push(deviceToken, payload);
    } catch (Exception e) {
        e.printStackTrace();
    }
    }
}


问:
Verify SAML Response from ADFS
I have problems verifying a SAML-response I get form an ADFS Server. I get the response as an url like CALLBACK_URL?SAMLResponse=ENCODED_XML&Signature=SIGNATURE_VALUE&SigAlg=SIGNATURE_ALGORITHMwhile SIGNATURE_ALGORITHM is http://www.w3.org/2001/04/xmldsig-more#rsa-sha256. I managed to decode the response but I am not able to find a way to verify the response using the given signature.

My main problem is that the signature has a very unexpected format. Because of the given signature algorithm I expect the signature to have a length of 32 bytes but what I get when I base64-decode the signature is a string with length 256.

I expect that decoding the signature using base64 is not sufficient. Unfortunately I have not been able to find out what to do next so far. So my question is: What do I have to do to correctly decode the signature to be able to verify it?

答:
I believe you're conflating a hash with a signature.

The signature takes the hash of the message as input and encrypts it with a key. In your case the SigAlg parameter indicates that the 32 byte hash of the SAML message is encrypted with (apparently) a 2048 bits RSA private key, possibly using PKCS#1 v1.5 padding as described in https://www.rfc-editor.org/rfc/rfc6931#section-2.3.2 resulting in a 256 byte signature that can be verified with the associated 2048 bits RSA public key of the sender.

Apart from that: I assume your referring to a SAML request rather than a SAML response since the latter must not be sent by using the HTTP redirect binding as written down in the Web Browser SSO Profile specification, page 16: https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf  (top of the page):

Identity Provider issues  to Service Provider In step 5, the identity provider issues a  message to be delivered by
the user agent to the service provider. Either the HTTP POST, or HTTP
Artifact binding can be used to transfer the message to the service
provider through the user agent. The message may indicate an error, or
will include (at least) an authentication assertion. The HTTP Redirect
binding MUST NOT be used, as the response will typically exceed the
URL length permitted by most user agents.

Title: Verify SAML Response from ADFS


问:
how to sort an array based on the contents of another array
I have an array X = [12,14,12,45,12] and another array Y = [34,12,23,47,20]. I am sorting the X array, so now X = [12,12,12,14,45]. Now I want to sort Y as Y = [34,23,20,12,47]. Any help would be appreciated. Thanks</p>

答:
You can build an array of indexes and sort it using a custom comparator function that references X and, then, use that array to "sort" Y:

var X = [12,14,12,45,12];
var Y = [34,12,23,47,20];
var xIndexes = [];
X.forEach((value, index) => xIndexes.push(index));

xIndexes.sort((a, b) => X[a] < X[b] ? -1 : X[a] > X[b] ? 1 : 0);

var newX = [];
var newY = [];

xIndexes.forEach((index) => {
  newX.push(X[index]);
  newY.push(Y[index]);
});

console.log(newX);
console.log(newY);```


问:
TypeError: keytar.addPassword is not a function on electron
I am trying to use keytar at my electron project, but I got this error:

TypeError: keytar.addPassword is not a function

I saw the docs but it seems that addPassword does not exist.

My main.js is:

```<code>const electron = require('electron');
const keytar = require('keytar');

const { app, BrowserWindow } = electron;

const path = require('path');
const url = require('url');

let mainWindow;
let appIcon;

function createWindow() {
  keytar.addPassword('KeytarTest', 'AccountName', 'secret');
  const secret = keytar.getPassword('KeytarTest', 'AccountName');
  console.log(secret);
  const { width, height } = electron.screen.getPrimaryDisplay().workAreaSize;
  mainWindow = new BrowserWindow({ width, height });

  mainWindow.loadURL(startUrl);

  const contents = mainWindow.webContents;

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.on('ready', createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});
</code>```

Can anyone help me?

答:
I saw the docs but it seems that addPassword does not exist.

Yes, that's right. The function addPassword does not exist and that's why you're getting this TypeError.

In general, this has nothing to do with Electron, because the keytar package just does not provide the function you were trying to call.

If a function is not mentioned in the docs, it's most likely to not exist.

Body:
I am trying to use keytar at my electron project, but I got this error:

TypeError: keytar.addPassword is not a function

I saw the docs but it seems that addPassword does not exist.

My main.js is:

const electron = require('electron');
const keytar = require('keytar');

const { app, BrowserWindow } = electron;

const path = require('path');
const url = require('url');

let mainWindow;
let appIcon;

function createWindow() {
  keytar.addPassword('KeytarTest', 'AccountName', 'secret');
  const secret = keytar.getPassword('KeytarTest', 'AccountName');
  console.log(secret);
  const { width, height } = electron.screen.getPrimaryDisplay().workAreaSize;
  mainWindow = new BrowserWindow({ width, height });

  mainWindow.loadURL(startUrl);

  const contents = mainWindow.webContents;

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.on('ready', createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});

Can anyone help me?


问:
How to resize AlertDialog on the Keyboard display
I have a AlertDialog box with approximately 10 controls (text and TextView) on it. These controls are in a ScrollView with AlertDialog, plus I got 2 buttons positive and negative. The issue I have is when the soft keyboard pops up the two buttons are hidden behind the keyboard.

I was looking for something like redraw function on my inner View or the dialog box. Below is the screen shot of what I am talking about.

答:
Nothing worked for me except adjustPan

as per the documentation

The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.

So just simply use it in your onCreate() or onCreateView() method like:

```<code>getDialog().getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
</code>```

Or simply put android:windowSoftInputMode="adjustPan" in manifest for the Activiry in which we are playing with dialogs

and use android:windowSoftInputMode="adjustResize|stateHidden" in each edittext which will help the user to navigate to next textbox easily.

Point to remember

Never use MATCH_PARENT to make the dialog full screen as adjustPan will not work here. If anyone wants to make the dialog to fit the screen, just use points till 0.96 (not more than this) for the height, so the keyboard will properly reach to the edittext. I did like below :

```<code>@Override
public void onStart()
{
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null)
    {
        //int height = ViewGroup.LayoutParams.MATCH_PARENT;
        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        Display display = getActivity().getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        //int width = (int)(size.x * 0.96);
        int h = (int)(size.y * 0.96);

        dialog.getWindow().setLayout(width, h);
    }
}
</code>```

Look, If I will use the total height (MATCH_PARENT) then soft_keyboard will squize the dialog. But if I will use points for the height (here 0.96 which is almost near to match_parent), then it will properly work.

Hope it will help someone :)

ContentLicense: CC BY-SA 4.0

Body:
Nothing worked for me except adjustPan

as per the documentation

The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.

So just simply use it in your onCreate() or onCreateView() method like:

getDialog().getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Or simply put android:windowSoftInputMode="adjustPan" in manifest for the Activiry in which we are playing with dialogs

and use android:windowSoftInputMode="adjustResize|stateHidden" in each edittext which will help the user to navigate to next textbox easily.

Point to remember

Never use MATCH_PARENT to make the dialog full screen as adjustPan will not work here. If anyone wants to make the dialog to fit the screen, just use points till 0.96 (not more than this) for the height, so the keyboard will properly reach to the edittext. I did like below :

@Override
public void onStart()
{
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null)
    {
        //int height = ViewGroup.LayoutParams.MATCH_PARENT;
        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        Display display = getActivity().getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        //int width = (int)(size.x * 0.96);
        int h = (int)(size.y * 0.96);

        dialog.getWindow().setLayout(width, h);
    }
}

Look, If I will use the total height (MATCH_PARENT) then soft_keyboard will squize the dialog. But if I will use points for the height (here 0.96 which is almost near to match_parent), then it will properly work.

Hope it will help someone :)


问:
How does one test item membership in an unordered sequence (C++)?
I've used python for a long time, and I'm just beginning to use C++

In python, if one has a set or a dictionary it is relatively easy to get a boolean value indicating whether or not a particular item is in that sequence using the in keyword.
i.e.

```<code>a = set(2,4,3)
if 4 in a
print "yes, 4 is in a, thank you for asking!"
</code>```

it's much more efficient than doing this:

```<code>a = [2,3,4]
for number in a
>if number == 4
>>return "yes, 4 is in a, thank you for asking!"
</code>```

is there a way to do make a membership test simple and efficient in cpp or do you always have to iterate through some ordered sequence?

答:
```<code>template<typename T>
bool contains(const std::set<T>& a, const T& value) {
    return a.find(value) != a.end();
}

if (contains(a, 4)) {
    std::cout << "A contains 4\n";
}
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I've used python for a long time, and I'm just beginning to use C++

In python, if one has a set or a dictionary it is relatively easy to get a boolean value indicating whether or not a particular item is in that sequence using the in keyword.
i.e.

a = set(2,4,3)
if 4 in a
print "yes, 4 is in a, thank you for asking!"

it's much more efficient than doing this:

a = [2,3,4]
for number in a
>if number == 4
>>return "yes, 4 is in a, thank you for asking!"

is there a way to do make a membership test simple and efficient in cpp or do you always have to iterate through some ordered sequence?


问:
What is the difference between a composite data type and a data structure?
I read that a character array in C is a composite data type because it is a sequence of characters, but then in Java a String is a class and Wikipedia says that a class is data structure, I am confused.</p>

答:
Every Data Type is a Data Structure but nor every data structure is a data type.

A data type is an entity that can hold data.
A data type of the simplest form is a primitive data type.
A more complex data type made up of primitive data types is a composite data type

A Data structure becomes different from a data type when it hold Relationships between the entities stored, along with the entities.
here the entities are the data types. but the data types together with the relationships form the data structure.


问:
Xcode 8.3 can't connect Action which is defined in AppDelegate
Follow the Ry's Cocoa Book step by step, but everything is not as fine as demonstration in this book.

Im using latest Xcode8.3, and something called storyboard really makes me confusing,no xnib file exists...

what should I do

答:
Give the action the class name.</p>

```<code>- (IBAction)sayHello: (NSButton *)sender {

}
</code>```

Body:
Give the action the class name.

- (IBAction)sayHello: (NSButton *)sender {

}


问:
How to get the tag and its text using htmlagility
```<code>HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            string html = null;
            html =
            "<body> " +
                "<p class=\"hang12\">“What is Lorem Ipsum?” <i>Lorem Ipsum is simply dummy text</i> Lorem Ipsum has been the</p>" +
                "<p class=\"hang12\">when an unknown printer took a galley of type <i>It has survived not only five centuries,</i>.</p>" +
                "<p class=\"hang12\">but also the  <i>remaining essentially </i> </p>" +
                "<p class=\"hang12\">with the release of Letraset sheets containing Lorem Ipsum passages, <i>and more recently with desktop</i>. 1944.</p>" +
                "</body>";

            doc.LoadHtml(html);
            foreach (var item in doc.DocumentNode.Descendants())
            {
                chNodes(item);
            }

public void chNodes(HtmlAgilityPack.HtmlNode node)
        {
            try
            {
                if (node.HasChildNodes)
                {
                    foreach (var item in node.ChildNodes)
                    {
                        chNodes(item);
                    }
                }
                else
                {
                    Console.WriteLine("************");
                    Console.WriteLine(node.Line);
                    Console.WriteLine(node.LinePosition);
                    Console.WriteLine("************");
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                throw ex;
            }
        }
</code>```

My code above get the first position of the opening tag found.  But i can't get the position of the closing tag.  How can i solve it? I need those values to highlight the text in the webbrowser control. thank you.

答:
you can get using following code try this</p>

```<code>foreach (var item in doc.DocumentNode.SelectNodes("//p[@class='hang12']"))
{
     item.innerText;
     item.innerHtml;
}
</code>```

Body:
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            string html = null;
            html =
            " " +
                "
“What is Lorem Ipsum?” Lorem Ipsum is simply dummy text Lorem Ipsum has been the
" +
                "
when an unknown printer took a galley of type It has survived not only five centuries,.
" +
                "
but also the  remaining essentially
" +
                "
with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop. 1944.
" +
                "";

            doc.LoadHtml(html);
            foreach (var item in doc.DocumentNode.Descendants())
            {
                chNodes(item);
            }

public void chNodes(HtmlAgilityPack.HtmlNode node)
        {
            try
            {
                if (node.HasChildNodes)
                {
                    foreach (var item in node.ChildNodes)
                    {
                        chNodes(item);
                    }
                }
                else
                {
                    Console.WriteLine("************");
                    Console.WriteLine(node.Line);
                    Console.WriteLine(node.LinePosition);
                    Console.WriteLine("************");
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                throw ex;
            }
        }

My code above get the first position of the opening tag found.  But i can't get the position of the closing tag.  How can i solve it? I need those values to highlight the text in the webbrowser control. thank you.

Body:
you can get using following code try this

foreach (var item in doc.DocumentNode.SelectNodes("//p[@class='hang12']"))
{
     item.innerText;
     item.innerHtml;
}


问:
V Json Data is not getting read in Hive Table
I am reading one line json data from Twitter in a Hive External Table. The table gets created but while reading the data, I get an error. I want to read the hashtags. I've followed the below steps:

```<code>hive (test)> add jar /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar;
Added /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar to class path
Added resource: /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar
</code>```

Data in file:

```<code>hive (test)> dfs -cat abhijit_hdfs/flume2/tweets/Twitter_test.js;

"entities":{"symbols":[],"urls":[],"hashtags":[{"text":"AchieveMore","indices":[56,68]}]}
</code>```

DDL statement

```<code>hive (test)> create external table tt4
           > (entities struct<hashtags:array<struct<text:string>>>)
           > row format serde 'com.cloudera.hive.serde.JSONSerDe'
           > LOCATION '/user/training/abhijit_hdfs/flume2/tweets/' ;
OK

Time taken: 0.193 seconds.
hive (test)> select * from tt4;
OK
Failed with exception java.io.IOException:org.apache.hadoop.hive.serde2.SerDeException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of VALUE_STRING token
 at [Source: java.io.StringReader@1cc892e; line: 1, column: 1]
Time taken: 0.384 seconds
</code>```

Please Guide.

答:
This looks like a non-Hadoop or hive related issue and rather a JSON serializer error the serde which you are pointing to internally uses org.codehaus.jackson

On trying the JSON it seems to have this error

```<code> `Error: Parse error on line 1:"entities":{"symbols":[],"urls
                               ----------^
        Expecting 'EOF', '}', ',', ']', got ':'`
</code>```

I haven't tried the whole setup but the JSON seems to be missing an { at start to be a good parsable JSON

```<code>{"entities":{"symbols":[],"urls":[],"hashtags":[{"text":"AchieveMore","indices":[56,68]}]}}
</code>```

Body:
I am reading one line json data from Twitter in a Hive External Table. The table gets created but while reading the data, I get an error. I want to read the hashtags. I've followed the below steps:

hive (test)> add jar /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar;
Added /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar to class path
Added resource: /usr/lib/hive/lib/hive-serdes-1.0-SNAPSHOT.jar

Data in file:

hive (test)> dfs -cat abhijit_hdfs/flume2/tweets/Twitter_test.js;

"entities":{"symbols":[],"urls":[],"hashtags":[{"text":"AchieveMore","indices":[56,68]}]}

DDL statement

hive (test)> create external table tt4
           > (entities struct<hashtags:array<struct<text:string>>>)
           > row format serde 'com.cloudera.hive.serde.JSONSerDe'
           > LOCATION '/user/training/abhijit_hdfs/flume2/tweets/' ;
OK

Time taken: 0.193 seconds.
hive (test)> select * from tt4;
OK
Failed with exception java.io.IOException:org.apache.hadoop.hive.serde2.SerDeException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of VALUE_STRING token
 at [Source: java.io.StringReader@1cc892e; line: 1, column: 1]
Time taken: 0.384 seconds

Please Guide.

Body:
This looks like a non-Hadoop or hive related issue and rather a JSON serializer error the serde which you are pointing to internally uses org.codehaus.jackson

On trying the JSON it seems to have this error

 `Error: Parse error on line 1:"entities":{"symbols":[],"urls
                               ----------^
        Expecting 'EOF', '}', ',', ']', got ':'`

I haven't tried the whole setup but the JSON seems to be missing an { at start to be a good parsable JSON

{"entities":{"symbols":[],"urls":[],"hashtags":[{"text":"AchieveMore","indices":[56,68]}]}}