0
votes

i'm learning sockets and i have this program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace client
{
public class MyClient
{
    static ManualResetEvent _clientDonte = new ManualResetEvent(false);
    private static Socket _clientSocket;
    private SocketAsyncEventArgs _connectSocketEventArg;
    private CancellationTokenSource _cancelationTokenSource;

    public MyClient()
    {

    }

    public void Start(string address, uint port)
    {
        _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse(address), (int)port);
        _connectSocketEventArg = new SocketAsyncEventArgs();

        _connectSocketEventArg.Completed += ConnectSocketEventArgCompleted;
        _connectSocketEventArg.RemoteEndPoint = serverEP;
        _connectSocketEventArg.UserToken = _clientSocket;

        _clientSocket.ConnectAsync(_connectSocketEventArg);
        _clientDonte.WaitOne();
        Console.WriteLine("DAJESZ KURWA, NAPISZ COS!");
        while (true)
        {
            SendFromConsole();
        }

    }

    private void SendFromConsole()
    {
        var message = Console.ReadLine();
        var buff = Encoding.ASCII.GetBytes(message);
        _connectSocketEventArg.SetBuffer(buff, 0, buff.Length);
        _clientSocket.SendAsync(_connectSocketEventArg);
    }

    private void ConnectSocketEventArgCompleted(object sender, SocketAsyncEventArgs e)
    {
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Connect:
                ProcessConnect(e);
                break;
            case SocketAsyncOperation.Receive:
                ReceiveAsync(e);
                break;
            case SocketAsyncOperation.Send:
                SendAsync(e);
                break;
            default:
                throw new Exception("Invalid operation completed");
        }
    }

    private void SendAsync(SocketAsyncEventArgs e)
    {
        if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
        {
            Socket sock = e.UserToken as Socket;
            bool willRaiseEvent = sock.SendAsync(e);
            if (!willRaiseEvent)
            {
                ReceiveAsync(e);

            }
        }

    }

    private void ReceiveAsync(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            Console.WriteLine("SERVER>>: {0}", Encoding.ASCII.GetString(e.Buffer));
            Socket sock = e.UserToken as Socket;
        }
    }

    private void ProcessConnect(SocketAsyncEventArgs e)
    {
        _cancelationTokenSource = new CancellationTokenSource();
        Task.Factory.StartNew(ProgressConnect, _cancelationTokenSource.Token);

        if (e.SocketError == SocketError.Success)
        {
            Thread.Sleep(701);
            _cancelationTokenSource.Cancel();
            Console.WriteLine("Nawiazano polaczenie!");
            _clientDonte.Set();
        }
        else if (e.SocketError == SocketError.SocketError)
        {
            Console.WriteLine("Nie udalo sie! nacisnij cos by wyjsc");
            Console.ReadKey();
            Environment.Exit(0);
        }
    }

    private void ProgressConnect()
    {
        while (!_cancelationTokenSource.Token.IsCancellationRequested)
        {
            Console.Write(".");
            _cancelationTokenSource.Token.WaitHandle.WaitOne(700);
        }
    }
}
}

It is supposed to allow to write message, send it and wait for response asynchronously. Unfortunately when i send first message it's falling into infinite loop of sending. I have seen this Reusing SocketAsyncEventArgs with ReceiveAsync results in infinite loop topic but it didnt help.

1

1 Answers

1
votes

I never used this construction, but;

The infinite loop of sending might be, you never check if the bytes you are trying to send are sent. You might want to check if the BytesTransferred property is equal to the bytes you are trying to sent.


Also, you are blocking the current thread with the manual reset event.. Why aren't you using the non-async Connect()?