In my C# server-client program I have following isue:
after logging to server with one of clients server automatically goes off with StackOverFlowException after connecting with IP and typing "LOGIN xxxxxxx".
Client code
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace SIKTcpClient
{
class Program
{
private const int Port = 3000;
private static Socket _socket;
private const int attemptsLimit = 2;
private const int BufferSize = 2048;
private static byte[] buffer = new Byte[BufferSize];
private static string _login;
static void Main(string[] args)
{
Console.WriteLine("Write ip adress");
var input = Console.ReadLine();
var ipAdress = input.Length < 2 ? GetIpAdress() : input;
if (input.Length < 2)
Console.WriteLine(ipAdress);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Connect(ipAdress);
Console.WriteLine("Your login");
try
{
if (input.Length < 2)
{
Console.WriteLine(_login);
_socket.Send(Encoding.ASCII.GetBytes(_login));
}
while (true)
{
var result = Console.ReadLine();
var bytes = Encoding.ASCII.GetBytes(result);
_socket.Send(bytes);
}
}
catch (SocketException)
{
Console.WriteLine("Server was shut down.");
}
catch(Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
static void Connect(string ipAdress)
{
var attempts = 0;
while (!_socket.Connected && attempts < attemptsLimit)
{
try
{
++attempts;
var result = _socket.BeginConnect(ipAdress, Port, EndConnect, null);
result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
Thread.Sleep(3000);
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
if(!_socket.Connected)
{
Console.WriteLine("Could not connect to server");
return;
}
}
private static void EndConnect(IAsyncResult asyncResult)
{
try
{
_socket.EndConnect(asyncResult);
if (_socket.Connected)
{
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
}
else
{
Console.WriteLine("End of connection attempt, fail to connect...");
}
}
catch (SocketException)
{
Console.WriteLine("Waiting for server...");
}
catch(Exception ex)
{
Console.WriteLine("Cant connnect to server... " + ex.Message);
}
}
private static void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
var socket = (Socket)asyncResult.AsyncState;
if (socket.Connected)
{
var received = socket.EndReceive(asyncResult);
if (received > 0)
{
var data = new byte[received];
Buffer.BlockCopy(buffer, 0, data, 0, data.Length);
var message = Encoding.UTF8.GetString(data);
if (!string.IsNullOrWhiteSpace(message))
Console.Write("Server: " + Encoding.UTF8.GetString(data));
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
}
}
catch(SocketException)
{
Console.WriteLine("Server was shut down.");
}
catch(Exception ex)
{
Console.WriteLine("Receive callback failed "+ ex.Message);
}
}
private static string GetIpAdress()
{
var random = new Random();
var r = random.Next(100000000);
_login = "LOGIN " + r;
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530);
var endPoint = socket.LocalEndPoint as IPEndPoint;
var localIP = endPoint.Address.ToString();
return localIP;
}
}
}
}
server code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SIKTcpServer.Constants;
using SIKTcpServer.Models;
using SIKTcpServer.Models.Cards;
namespace SIKTcpServer
{
class Program
{
private static Socket _socket;
private const int Port = 3000;
private const int BufferSize = 2048;
private static byte[] _buffer = new byte[BufferSize];
private static List<Player> _players = new List<Player>();
private static bool _gameStarted = false;
private static List<Player> _playersInRound;
private static readonly int[] _ids = new int[5] { 1, 2, 3, 4, 5 };
private static List<AbstractCard> _turnCards;
static void Main(string[] args)
{
Console.Title = "Server";
GatherPlayers();
Console.ReadKey();
}
private static void GatherPlayers()
{
//var a = LoadCards();
Console.WriteLine("Waiting for players...");
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, Port));
_socket.Listen(0);
_socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
while(_players.Count < 2) { }
Console.WriteLine("asd");
}
private static void AcceptCallback(IAsyncResult asyncResult)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket = _socket.EndAccept(asyncResult);
if (_players.Count > 2 || _gameStarted)
{
socket.Send(GetAsciiBytes("Sorry we have 5 players already"));
return;
}
socket.Send(GetAsciiBytes("CONNECT"));
Console.WriteLine("Connected new socket");
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
_socket.BeginAccept(new AsyncCallback(AcceptCallback), socket);
}
catch
{
RemovePlayer(socket);
socket.Dispose();
}
}
private static void ReceiveCallback(IAsyncResult asyncResult)
{
Socket current = (Socket)asyncResult.AsyncState;
int received;
try
{
received = current.EndReceive(asyncResult);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close();
RemovePlayer(current);
return;
}
byte[] recBuffer = new byte[received];
Array.Copy(_buffer, recBuffer, received);
string text = Encoding.ASCII.GetString(recBuffer);
Console.WriteLine("Received Text: " + text);
if (_players.Count > 4)
{
current.Send(GetAsciiBytes("Sorry we have 5 players already"));
current.Close();
current.Dispose();
}
else if (text.Length < 7 || text.Substring(0, 5) != "LOGIN" || string.IsNullOrWhiteSpace(text.Substring(6, 2)))
{
Console.WriteLine("Text is an invalid request");
var data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
current.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceiveCallback, current);
}
else
{
current.Send(GetAsciiBytes("OK"));
_players.Add(new Player(current));
Console.WriteLine("Player OK");
}
}
private static void Round()
{
StartRound();
while (_playersInRound.Count > 1 && _turnCards.Count > 0)
{
foreach (var player in _playersInRound)
{
if (player.IsEliminated)
{
}
if (player.SkipTurn)
{
player.SkipTurn = false;
continue;
}
var card = GetRandomCard();
player.Cards.Add(card);
player.Socket.Send(GetAsciiBytes($"YOUR MOVE {card.Name}"));
var playerCardsNames = player.Cards.Select(x => x.Name).ToArray();
if (player.HaveCountessAndKingOrPrince)
{
while(true)
{
player.Socket.Receive(_buffer, 0, _buffer.Length, SocketFlags.None);
}
}
var splittedMessage = GetStringFromBytes(_buffer).Split(new char[0]);
var choosenPlayer = Int32.Parse(splittedMessage[2] ?? "0");
var choosenSecondCard = splittedMessage[3] ?? "";
var playedCard = player.Cards.Where(x => x.Name.ToString() == splittedMessage[1]).First();
player.Cards.Where(x => x.Name == playedCard.Name).FirstOrDefault().Action(player, _playersInRound.Where(x => x.Id == choosenPlayer).FirstOrDefault(), choosenSecondCard);
//Array.Clear(_buffer, 0, _buffer.Length);
RemoveEliminatedPlayers();
}
}
}
private static void StartRound()
{
MixPlayers();
LoadCards();
GiveStartingCardsToPlayers();
foreach (var player in _playersInRound)
{
player.Socket.Send(GetAsciiBytes($"START {player.Id.ToString()} {player.Cards[0]}"));
}
}
private static void MixPlayers()
{
var ids = _ids.ToList();
var random = new Random();
for (var i = 0; i < 5; i++)
{
var randomListIndex = random.Next(ids.Count);
_playersInRound[i].Id = ids[randomListIndex];
ids.RemoveAt(randomListIndex);
}
_playersInRound.OrderBy(x => x.Id);
}
private static void RemovePlayer(Socket socket)
{
_players.Remove(_players.Where(x => x.Socket == socket).FirstOrDefault());
}
private static List<AbstractCard> LoadCards()
{
var allCards = new List<AbstractCard>();
var values = Enum.GetValues(typeof(CardName)).Cast<CardName>().ToArray();
foreach (var value in values)
{
for (var i = 0; i < (int)Enum.Parse(typeof(CardAmount), value.ToString()); i++)
{
switch (value)
{
case CardName.Baron:
allCards.Add(new BaronCard());
break;
case CardName.Countess:
allCards.Add(new CountessCard());
break;
case CardName.Guard:
allCards.Add(new GuardCard());
break;
case CardName.Handmaiden:
allCards.Add(new HandmaidenCard());
break;
case CardName.King:
allCards.Add(new KingCard());
break;
case CardName.Priest:
allCards.Add(new PriestCard());
break;
case CardName.Prince:
allCards.Add(new PrinceCard());
break;
case CardName.Princess:
allCards.Add(new PrincessCard());
break;
}
}
}
return allCards;
}
private static AbstractCard GetRandomCard()
{
var random = new Random();
var randomIndex = random.Next(_turnCards.Count);
var randomCard = _turnCards[randomIndex];
_turnCards.RemoveAt(randomIndex);
return randomCard;
}
private static void GiveStartingCardsToPlayers()
{
foreach (var player in _playersInRound)
{
player.Cards.Add(GetRandomCard());
}
}
private static void RemoveEliminatedPlayers()
{
Predicate<Player> eliminated = (Player player) => { return player.IsEliminated == true; };
_playersInRound.RemoveAll(eliminated);
_players.ForEach(x => x.ClearElimination());
}
private static byte[] GetAsciiBytes(string text)
{
return Encoding.ASCII.GetBytes(text);
}
private static string GetStringFromBytes(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
}
}
Sadly stackoverflow site says that it looks like my post is mostly code but i have described everything above so sorry for this pointless text here.
you have created the static buffer array which is giving you out stackoverflow exception this is because multiple clients requesting at the same time. they used this static buffer for both. it is not a good in development creating static buffer.
you have to comes up with some new login like this.
public class SocketPacketforROD
{
public System.Net.Sockets.Socket CurrentSocket;
//test
public int last_buffer_read = 0;
public int last_socket_payload_size = 0;
public byte[] Data = null; // new byte[Server.bufferLength];
public SocketPacketforROD_State m_state = SocketPacketforROD_State.socket_state_payload_size;
public void allocate(int bytes)
{
// socket_buffer_length = bytes;
Data = new byte[bytes];
}
}
Used this socket object class in your onreceiveddata method
string Data = Encoding.ASCII.GetString(socketData.Data);
Logger.WriteLog("Message Received length : " + Data.Length + " from: " + socketData.CurrentSocket.RemoteEndPoint, LogLevel.GENERALLOG);
socketData.m_state = SocketPacketforROD_State.socket_state_payload_size;
Setup Receive callback
private void SetupReceiveCallback(Socket objClientSocket)
{
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
SocketPacketforROD theSocPkt = new SocketPacketforROD();
theSocPkt.last_socket_payload_size = 4;
theSocPkt.allocate(4);
theSocPkt.CurrentSocket = objClientSocket;
Logger.WriteLog("After New Socket buffer Length : " + theSocPkt.Data.Length, LogLevel.GENERALLOG);
objClientSocket.BeginReceive(theSocPkt.Data, 0, theSocPkt.Data.Length, SocketFlags.None, recieveData, theSocPkt);
}
catch (OutOfMemoryException MemEXP)
{
Logger.WriteException(MemEXP);
}
catch (Exception E)
{
Logger.WriteException(E);
}
}
Related
So I have searched a lot of areas for this answer and I am confused on what this error is doing. Whenever I press the start server button...
...I get this error "An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll"
My code is quite long but I have no clue what to do...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private bool isserver = false;
public const int MAXSIZE = 10;
public Form1()
{
InitializeComponent();
clearoutput();
}
TcpListener tcpl = new TcpListener(IPAddress.Parse(getip()), 2546);
List<TcpClient> clients = new List<TcpClient>();
List<string> names = new List<string>();
bool CommandMode = false;
List<string> banlist = new List<string>();
TcpClient Client = new TcpClient();
//client setup
private void button1_Click(object sender, EventArgs e)
{
try {
Output.Text = Output.Text + "You have joined as a client";
Client = new TcpClient();
Client.Connect(IP_address.Text, 2546);
Thread myThread = new Thread(new ParameterizedThreadStart(Listen));
myThread.Start(Client);
//whenever you send a message you must include the next two lines
//Client.GetStream().Write(new byte[] { (byte)Encoding.Unicode.GetByteCount(name + " has joined") }, 0, 1);
//Client.GetStream().Write(Encoding.Unicode.GetBytes(name + " has joined"), 0, Encoding.Unicode.GetByteCount(name + " has joined"));
//the two lines above
Client.GetStream().Write(new byte[] { (byte)Encoding.Unicode.GetByteCount("\\join" + getip()) }, 0, 1);
Client.GetStream().Write(Encoding.Unicode.GetBytes("\\join" + getip()), 0, Encoding.Unicode.GetByteCount("\\join" + getip()));
}
catch { }
IP_address.Visible = false;
Join_btn.Visible = false;
Start_btn.Visible = false;
Output.Visible = true;
Input.Visible = true;
text1.Visible = true;
text1.Visible = true;
}
private void clearoutput()
{
Output.Text = "";
}
//server setup---
private void Start_btn_Click(object sender, EventArgs e)
{
isserver = true;
server_IP_lbl.Text = $"Since you are a server:\nYour ip address is : "+getip();
//if You need a new banlist make sure you click here and allow this
Write_to_output("you are a server");
try
{
StreamReader readerfrban = new StreamReader("banlist");
readerfrban.Close();
Write_to_output("we found a banlist \n no worries");
}
catch
{
Write_to_output("Error- could not find a banlist creating one now");
StreamWriter banlistmaker = new StreamWriter("banlist");
banlistmaker.Close();
}
//open banlist
StreamReader readerforban = new StreamReader("banlist");
string reader = "";
//read all bans in
do
{
reader = readerforban.ReadLine();
if (reader != null)
banlist.Add(reader);
} while (reader != null);
tcpl.Start();
//Thread AcceptSocketsThread = new Thread(AcceptSockets);
//AcceptSocketsThread.Start();
/* while (true)
{
string Message = Console.ReadLine();
if (Message.StartsWith("\\Kick"))
{
Console.Clear();
CommandMode = true;
int clientID = 0;
foreach (TcpClient client in clients)
{
Write_to_output(clientID.ToString() + ") " + names[clientID] + " " + client.Client.RemoteEndPoint);
clientID++;
}
Write_to_output("\n\n Enter the number of the person you want to kick");
TcpClient toRemove = clients[Convert.ToInt32(Console.ReadLine())];
toRemove.Close();
clients.Remove(toRemove);
CommandMode = false;
}
else if (Message.StartsWith("\\Reset"))
{
foreach (TcpClient client in clients)
{
client.Close();
}
clients.Clear();
Write_to_output("KICKED EVERY BODY");
}
else if (Message.StartsWith("\\ban"))
{
Console.Clear();
CommandMode = true;
int clientID = 0;
foreach (TcpClient client in clients)
{
Write_to_output(clientID.ToString() + ") " + names[clientID] + " " + client.Client.RemoteEndPoint);
clientID++;
}
Write_to_output("\n\n Enter the number of the person you want to kick and ban");
TcpClient toRemove = clients[Convert.ToInt32(Console.ReadLine())];
banlist.Add(toRemove.Client.RemoteEndPoint.ToString().Split(new char[] { ':' })[0]);
toRemove.Close();
clients.Remove(toRemove);
CommandMode = false;
}
//starts game
else
{
foreach (TcpClient client in clients)
{
SendMessage(Message, client);
}
}
}*/
IP_address.Visible = false;
Join_btn.Visible = false;
Start_btn.Visible = false;
Output.Visible = true;
Input.Visible = true;
text1.Visible = true;
text1.Visible = true;
}
void SendMessage(string message, TcpClient reciever)
{
try {
reciever.GetStream().Write(new byte[] { (byte)Encoding.Unicode.GetByteCount(message) }, 0, 1);
reciever.GetStream().Write(Encoding.Unicode.GetBytes(message), 0, Encoding.Unicode.GetByteCount(message));
}
catch
{
Write_to_output("Was unable to send to any users error code 1.0.0.0");
}
}
void AcceptSockets()
{
while (true)
{
TcpClient client = tcpl.AcceptTcpClient();
Thread myThread = new Thread(new ParameterizedThreadStart(Listen));
clients.Add(client);
myThread.Start(client);
}
}
void setname(string name)
{
names.Add(name);
}
void Listen(object obj)
{
TcpClient TCPClient = (TcpClient)obj;
while (true)
{
try
{
byte[] fBuffer = new byte[1];
TCPClient.GetStream().Read(fBuffer, 0, 1);
byte[] buffer = new byte[(int)fBuffer[0]];
TCPClient.GetStream().Read(buffer, 0, (int)fBuffer[0]);
string message = Encoding.Unicode.GetString(buffer).Trim();
if (message.StartsWith("\\join"))
{
message = message.Remove(0, 5);
int a = 0;
for (int i = 0; i < banlist.Count; i++)
{
if (message.StartsWith(banlist[i]))
{
a = 1;
}
}
if (a == 0)
{
//int namespaceer = 0;
//foreach (char chars in message)
//{
// namespaceer += 1;
// if (chars == '+')
// break;
//}
// message = message.Remove(0, namespaceer);
}
else
{
//Write_to_output("Person on banlist");
// TcpClient toRemove = clients[Convert.ToInt32(Console.ReadLine())];
//toRemove.Close();
}
}
else
{
foreach (TcpClient client in clients)
{
if (client != TCPClient)
{
SendMessage(message, client);
}
}
if (!CommandMode)
{
Write_to_output(message.Trim());
}
else
{
}
}
}
catch (Exception e)
{
Write_to_output(e.ToString());
}
}
}
static string getip()
{
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily.ToString() == "InterNetwork")
{
localIP = ip.ToString();
}
}
return localIP;
}
public void Write_to_output(string towrite)
{
//check outputs length
int numLines = 0;
string text = Output.Text;
numLines = Text.Split('\n').Length;
if (numLines == MAXSIZE)
{
Output.Text = towrite;
}
else
{
Output.Text = Output.Text + $"\n" + towrite;
}
}
private void Input_Leave(object sender, EventArgs e)
{
string message = Input.Text;
if (isserver == false)
{
//send client code
SendMessage(message,Client);
}
else
{
//send server code
foreach (TcpClient client in clients)
{
SendMessage(message, client);
}
}
}
}
}
Please help me...
Check if the port TCP 2546 is not busy by another process or code instance on the listening machine.
Or choose another free port to listen to.
I was trying to create an application to create a bound between two clients(two form application) to transmit through TCP protocol some data. I wrote the applicatin in C# using System.Net.Sockets (I am a beginner in System.Net) and I get this error:
System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.2.101:100 at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.Connect(EndPoint remoteEP) at System.Net.Sockets.Socket.Connect(IPAddress address, Int32 port) at Client_003.Form1.LoopConnect()
I must say that this went well on my machine and another one that is bound with mine by router.
This is the code for server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace Server_003
{
class Program
{
private static List<Socket> _clientSockets = new List<Socket>();
private static List<string> _numeClient = new List<string>();
private static List<int> _indexPartener = new List<int>();
private static byte[] _buffer = new byte[10000];
private static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
SetUpServer();
Console.ReadLine();
}
private static void SetUpServer()
{
//byte[] test = Encoding.ASCII.GetBytes("lose partener");
//Console.WriteLine(test.Length);
Console.WriteLine("Seting up server ... ");
_serverSocket.Bind(new IPEndPoint(IPAddress.Parse("192.168.2.101"), 100));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null);
}
private static string GetNume()
{
int index = 0;
if (_numeClient.Count == 0)
return "Client 0";
else
for (int i = 0; i < _numeClient.Count; i++)
if (_numeClient[i] != "Client " + index.ToString())
return "Client " + index.ToString();
else
index++;
return "Client " + index.ToString();
}
private static void AcceptCallBack(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR); //return client socket
_clientSockets.Add(socket);
_indexPartener.Add(-1);
_numeClient.Add(GetNume());
Console.WriteLine("Client conected with IP: " + socket.RemoteEndPoint);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null); //permitem sa mai accepte clienti
}
private static string GetNumeClienti()
{
string clienti = "";
for (int i = 0; i < _numeClient.Count; i++)
if(_indexPartener[i] == -1)
clienti += i.ToString() + " " + _numeClient[i] + "\r\n";
return clienti;
}
private static string GetClientiPlusParteneri()
{
string clienti = "";
for (int i = 0; i < _numeClient.Count; i++)
if (_indexPartener[i] == -1)
clienti += _numeClient[i] + " Null\r\n";
else
clienti += _numeClient[i] + " " + _numeClient[_indexPartener[i]] + "\r\n";
return clienti;
}
private static void ReceiveCallBack(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
int index = _clientSockets.IndexOf(socket);
int receive = socket.EndReceive(AR);
byte[] DataBuffReceive = new byte[receive];
if (receive == 13)
_indexPartener[index] = -1;
else
if (_indexPartener[index] == -1)
{
Array.Copy(_buffer, DataBuffReceive, receive);
string text = Encoding.ASCII.GetString(DataBuffReceive);
string raspuns = "Invalid request!";
if (text.ToLower() == "get time")
{
raspuns = DateTime.Now.ToLongTimeString();
}
if (text.IndexOf(' ') > 0 && text.Substring(0, text.IndexOf(' ')) == "NuMe")
{
_numeClient[index] = text.Substring(text.IndexOf(' ') + 1);
raspuns = "Nume setat la " + _numeClient[index];
}
if (text.ToLower() == "get clienti liberi")
raspuns = GetNumeClienti();
if (text.ToLower() == "get clienti si parteneri")
raspuns = GetClientiPlusParteneri();
if (text.ToLower() == "e--")
{
raspuns = "Deconectat!";
_clientSockets.RemoveAt(index);
_numeClient.RemoveAt(index);
_indexPartener.RemoveAt(index);
return;
}
byte[] DataBuffSend = Encoding.ASCII.GetBytes(raspuns);
socket.BeginSend(DataBuffSend, 0, DataBuffSend.Length, SocketFlags.None, new AsyncCallback(SendCallBack), socket);
}
else
_clientSockets[index].BeginSend(DataBuffReceive, 0, DataBuffReceive.Length, SocketFlags.None, new AsyncCallback(SendCallBack), _clientSockets[index]);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
}
private static void SendCallBack(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
}
}
And this is the code for client(a form application):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Client_003
{
public partial class Form1 : Form
{
private byte[] _buffer = new byte[10000];
private Socket _clientSoket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private bool continuare = true;
public Form1()
{
InitializeComponent();
groupBox1.Text = "";
groupBox1.Visible = false;
}
private void LoopConnect()
{
if (_clientSoket.Connected)
MessageBox.Show("It's connected!");
else
{
while (!_clientSoket.Connected)
{
try
{
MessageBox.Show("Trying to connect!");
_clientSoket.Connect(IPAddress.Parse("192.168.2.101"), 100);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
textBox2.Clear();
textBox2.Text = "Connected!";
groupBox1.Visible = true;
}
private void primire()
{
if (continuare)
{
int rec = _clientSoket.Receive(_buffer);
byte[] data = new byte[rec];
Array.Copy(_buffer, data, rec);
string text = Encoding.ASCII.GetString(data);
if (text.IndexOf(' ') > 0 && text.ToLower().Substring(0, text.IndexOf(' ')) == "acceptare_partener")
{
DialogResult raspuns = MessageBox.Show("Acceptati ca partener pe " + text.Substring(text.IndexOf(' ') + 1), "Acceptare partener", MessageBoxButtons.YesNo);
if (raspuns == DialogResult.Yes)
{
byte[] cerere = Encoding.ASCII.GetBytes("yes");
_clientSoket.Send(cerere);
primire(); // expected confirmation
}
else
{
byte[] cerere = Encoding.ASCII.GetBytes("no");
_clientSoket.Send(cerere);
primire(); // expected confirmation
}
}
textBox2.Text += "\r\n" + text;
}
}
private void button1_Click(object sender, EventArgs e)
{
LoopConnect();
}
private void button2_Click(object sender, EventArgs e)
{
byte[] cerere = Encoding.ASCII.GetBytes(textBox1.Text);
_clientSoket.Send(cerere);
textBox1.Clear();
primire();
}
private void button3_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_clientSoket.Connected)
{
continuare = false;
byte[] cerere = Encoding.ASCII.GetBytes("e--");
_clientSoket.Send(cerere);
_clientSoket.Close();
}
}
}
}
can someone please help me out with this... I've been struggling all day.
So I'm trying to learn Async sockets which is something that's been giving me trouble.
The issue is basically the way I'm updating the ListBox with people who have joined the chat room's names:
Basically what I'm doing is having each client send "!!addlist [nickname]" when they join the server.
It's not ideal as it doesn't check for duplicates etc. but now I just want to know why it won't work.
Whenever somebody adds a name they haven't seen before, they will also send "!!addlist [nick]"
In this way, every time someone joins, the lists should be updated for everyone.
The issue seems to be that all the clients start communicating at the same time and it interferes with the buffer.
I've tried using a separate buffer for every client so that's not the issue.
I've tried using lock() but that doesn't seem to be working either.
Essentially what happens is the buffers seem to truncate; where there is data from two different people in the same buffer.
Please just tell me what I'm doing wrong with the buffers or on the client side:
Note that the async socket is using Send instead of BeginSend.
I've tried both methods and they run into the same issue... so it's probably client side?
public partial class Login : Form
{
private ChatWindow cw;
private Socket serverSocket;
private List<Socket> socketList;
private byte[] buffer;
private bool isHost;
private bool isClosing;
public void startListening()
{
try
{
this.isHost = true; //We're hosting this server
cw.callingForm = this; //Give ChatForm the login form (this) [that acts as the server]
cw.Show(); //Show ChatForm
cw.isHost = true; //Tell ChatForm it is the host (for display purposes)
this.Hide(); //And hide the login form
serverSocket.Bind(new IPEndPoint(IPAddress.Any, int.Parse(portBox.Text))); //Bind to our local address
serverSocket.Listen(1); //And start listening
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //When someone connects, begin the async callback
cw.connectTo("127.0.0.1", int.Parse(portBox.Text), nicknameBox.Text); //And have ChatForm connect to the server
}
catch (Exception) { /*MessageBox.Show("Error:\n\n" + e.ToString());*/ } //Let us know if we ran into any errors
}
public void AcceptCallback(IAsyncResult AR)
{
try
{
Socket s = serverSocket.EndAccept(AR); //When someone connects, accept the new socket
socketList.Add(s); //Add it to our list of clients
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), s); //Begin the async receive method using our buffer
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //And start accepting new connections
}
catch (Exception) {}
}
public void ReceiveCallback(IAsyncResult AR) //When a message from a client is received
{
try
{
if (isClosing)
return;
Socket s = (Socket)AR.AsyncState; //Get the socket from our IAsyncResult
int received = s.EndReceive(AR); //Read the number of bytes received (*need to add locking code here*)
byte[] dbuf = new byte[received]; //Create a temporary buffer to store just what was received so we don't have extra data
Array.Copy(buffer, dbuf, received); //Copy the received data from our buffer to our temporary buffer
foreach (Socket client in socketList) //For each client that is connected
{
try
{
if (client != (Socket)AR.AsyncState) //If this isn't the same client that just sent a message (*client handles displaying these*)
client.Send(dbuf); //Send the message to the client
}
catch (Exception) { }
} //Start receiving new data again
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), s);
}
catch (Exception) { /*cw.output("\n\nError:\n\n" + e.ToString());*/ }
}
public void SendCallback(IAsyncResult AR)
{
try
{
Socket s = (Socket)AR.AsyncState;
s.EndSend(AR);
}
catch (Exception) { /*cw.output("\n\nError:\n\n" + e.ToString());*/ }
}
Here is the client side:
public void getData()
{
try
{
byte[] buf = new byte[1024];
string message = "";
while(isConnected)
{
Array.Clear(buf, 0, buf.Length);
message = "";
clientSocket.Receive(buf, buf.Length, SocketFlags.None);
message = Encoding.ASCII.GetString(buf);
if (message.StartsWith("!!addlist"))
{
message = message.Replace("!!addlist", "");
string userNick = message.Trim();
if (!namesBox.Items.Contains(userNick))
{
addNick(userNick.Trim());
}
continue;
}
else if (message.StartsWith("!!removelist"))
{
message = message.Replace("!!removelist", "");
string userNick = message.Trim();
removeNick(userNick);
output("Someone left the room: " + userNick);
continue;
}
else if (!namesBox.Items.Contains(message.Substring(0, message.IndexOf(":"))))
{
addNick(message.Substring(0, message.IndexOf(":")).Trim()); //So they at least get added when they send a message
}
output(message);
}
}
catch (Exception)
{
output("\n\nConnection to the server lost.");
isConnected = false;
}
}
Here is my addNick function that seems to fix some things?
public void addNick(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
output("Someone new joined the room: " + n);
sendRaw("!!addlist " + nickName);
}
}
I think the issue is that some of the packets are being skipped?
Maybe there's too much code in the client after Receive before it gets called again?
Should I create a separate thread for each message so that receive runs constantly? (Dumb)
Should I have my client use Async receives and sends as well?
I have a feeling that is the answer ^
With all of the checks I do, I managed to clean up the duplicate name issue... but i regularly receive messages with spaces and partial messages from other clients it seems.
Okay so, after messing with this for a long time, I have it relatively stable.
For starters, I added the following state object:
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public bool newConnection = true;
}
This makes it easy to keep track of each connection and gives each connection its own buffer.
The second thing I did was look for a new line in each message.
I wasn't looking for this in the original code and I believe this was the root of most issues.
I also gave the responsibility of dealing with username management to the server; something that I should have done from the start obviously.
Here is the current server code:
This code is in no way perfect and I'm continuously finding new errors the more I try to break it. I'm going to keep messing with it for awhile but at the moment, it seems to work decently.
public partial class Login : Form
{
private ChatWindow cw;
private Socket serverSocket;
private List<Socket> socketList;
private byte[] buffer;
private bool isHost;
private bool isClosing;
private ListBox usernames;
public Login()
{
InitializeComponent();
}
private void Login_Load(object sender, EventArgs e)
{
ipLabel.Text = getLocalIP();
cw = new ChatWindow();
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketList = new List<Socket>();
buffer = new byte[1024];
isClosing = false;
usernames = new ListBox();
}
public string getLocalIP()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
private void joinButton_Click(object sender, EventArgs e)
{
try
{
int tryPort = 0;
this.isHost = false;
cw.callingForm = this;
if (ipBox.Text == "" || portBox.Text == "" || nicknameBox.Text == "" || !int.TryParse(portBox.Text.ToString(), out tryPort))
{
MessageBox.Show("You must enter an IP Address, Port, and Nickname to connect to a server.", "Missing Info");
return;
}
this.Hide();
cw.Show();
cw.connectTo(ipBox.Text, int.Parse(portBox.Text), nicknameBox.Text);
}
catch(Exception otheree) {
MessageBox.Show("Error:\n\n" + otheree.ToString(),"Error connecting...");
cw.Hide();
this.Show();
}
}
private void hostButton_Click(object sender, EventArgs e)
{
int tryPort = 0;
if (portBox.Text == "" || nicknameBox.Text == "" || !int.TryParse(portBox.Text.ToString(), out tryPort)) {
MessageBox.Show("You must enter a Port and Nickname to host a server.", "Missing Info");
return;
}
startListening();
}
public void startListening()
{
try
{
this.isHost = true; //We're hosting this server
cw.callingForm = this; //Give ChatForm the login form (this) [that acts as the server]
cw.Show(); //Show ChatForm
cw.isHost = true; //Tell ChatForm it is the host (for display purposes)
this.Hide(); //And hide the login form
serverSocket.Bind(new IPEndPoint(IPAddress.Any, int.Parse(portBox.Text))); //Bind to our local address
serverSocket.Listen(1); //And start listening
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //When someone connects, begin the async callback
cw.connectTo("127.0.0.1", int.Parse(portBox.Text), nicknameBox.Text); //And have ChatForm connect to the server
}
catch (Exception) {}
}
public void AcceptCallback(IAsyncResult AR)
{
try
{
StateObject state = new StateObject();
state.workSocket = serverSocket.EndAccept(AR);
socketList.Add(state.workSocket);
state.workSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (Exception) {}
}
public void ReceiveCallback(IAsyncResult AR)
{
try
{
if (isClosing)
return;
StateObject state = (StateObject)AR.AsyncState;
Socket s = state.workSocket;
String content = "";
int received = s.EndReceive(AR);
if(received > 0)
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
content = state.sb.ToString();
if (content.IndexOf(Environment.NewLine) > -1) //If we've received the end of the message
{
if (content.StartsWith("!!addlist") && state.newConnection)
{
state.newConnection = false;
content = content.Replace("!!addlist", "");
string userNick = content.Trim();
if (isHost && userNick.StartsWith("!"))
userNick = userNick.Replace("!", "");
userNick = userNick.Trim();
if (userNick.StartsWith("!") || userNick == string.Empty || usernames.Items.IndexOf(userNick) > -1)
{
//Invalid Username :c get dropped
s.Send(Encoding.ASCII.GetBytes("Invalid Username/In Use - Sorry :("));
s.Shutdown(SocketShutdown.Both);
s.Disconnect(false);
s.Close();
socketList.Remove(s);
return;
}
usernames.Items.Add(userNick);
foreach (string name in usernames.Items)
{
if (name.IndexOf(userNick) < 0)
{
s.Send(Encoding.ASCII.GetBytes("!!addlist " + name + "\r\n"));
Thread.Sleep(10); //such a hack... ugh it annoys me that this works
}
}
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(Encoding.ASCII.GetBytes("!!addlist " + userNick + "\r\n"));
}
catch (Exception) { }
}
}
else if (content.StartsWith("!!removelist") && !state.newConnection)
{
content = content.Replace("!!removelist", "");
string userNick = content.Trim();
usernames.Items.Remove(userNick);
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(Encoding.ASCII.GetBytes("!!removelist " + userNick + "\r\n"));
}
catch (Exception) { }
}
}
else if (state.newConnection) //if they don't give their name and try to send data, just drop.
{
s.Shutdown(SocketShutdown.Both);
s.Disconnect(false);
s.Close();
socketList.Remove(s);
return;
}
else
{
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(System.Text.Encoding.ASCII.GetBytes(content));
}
catch (Exception) { }
}
}
}
Array.Clear(state.buffer, 0, StateObject.BufferSize);
state.sb.Clear();
s.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception) {
socketList.Remove(((StateObject)AR.AsyncState).workSocket);
}
}
public void SendCallback(IAsyncResult AR)
{
try
{
StateObject state = (StateObject)AR.AsyncState;
state.workSocket.EndSend(AR);
}
catch (Exception) {}
}
private void Login_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
this.isClosing = true;
if (this.isHost)
{
foreach (Socket c in socketList)
{
if (c.Connected)
{
c.Close();
}
}
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
serverSocket = null;
serverSocket.Dispose();
}
socketList.Clear();
}
catch (Exception) { }
finally
{
Application.Exit();
}
}
}
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public bool newConnection = true;
}
The client code (work in progress):
public partial class ChatWindow : Form
{
private Socket clientSocket;
private Thread chatThread;
private string ipAddress;
private int port;
private bool isConnected;
private string nickName;
public bool isHost;
public Login callingForm;
private static object conLock = new object();
public ChatWindow()
{
InitializeComponent();
isConnected = false;
isHost = false;
}
public string getIP() {
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
public void displayError(string err)
{
output(Environment.NewLine + Environment.NewLine + err + Environment.NewLine);
}
public void op(string s)
{
try
{
lock (conLock)
{
chatBox.Text += s;
}
}
catch (Exception) { }
}
public void connectTo(string ip, int p, string n) {
try
{
this.Text = "Trying to connect to " + ip + ":" + p + "...";
this.ipAddress = ip;
this.port = p;
this.nickName = n;
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (!isHost)
{
op("Connecting to " + ipAddress + ":" + port + "...");
}
else
{
output("Listening on " + getIP() + ":" + port + "...");
}
clientSocket.Connect(ipAddress, port);
isConnected = true;
if (!isHost)
{
this.Text = "Connected to " + ipAddress + ":" + port + " - Nickname: " + nickName;
output("Connected!");
}
else
{
this.Text = "Hosting on " + getIP() + ":" + port + " - Nickname: " + nickName;
}
chatThread = new Thread(new ThreadStart(getData));
chatThread.Start();
nickName = nickName.Replace(" ", "");
nickName = nickName.Replace(":", "");
if(nickName.StartsWith("!"))
nickName = nickName.Replace("!", "");
namesBox.Items.Add(nickName);
sendRaw("!!addlist " + nickName);
}
catch (ThreadAbortException)
{
//do nothing; probably closing chat window
}
catch (Exception e)
{
if (!isConnected)
{
this.Hide();
callingForm.Show();
clearText();
MessageBox.Show("Error:\n\n" + e.ToString(), "Error connecting to remote host");
}
}
}
public void removeNick(string n)
{
if (namesBox.Items.Count <= 0)
return;
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
namesBox.Items.RemoveAt(x);
}
public void clearText()
{
try
{
lock (conLock)
{
chatBox.Text = "";
}
}
catch (Exception) { }
}
public void addNick(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
output("Someone new joined the room: " + n);
//sendRaw("!!addlist " + nickName);
}
}
public void addNickNoMessage(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
//sendRaw("!!addlist " + nickName);
}
}
public void getData()
{
try
{
byte[] buf = new byte[1024];
string message = "";
while(isConnected)
{
Array.Clear(buf, 0, buf.Length);
message = "";
int gotData = clientSocket.Receive(buf, buf.Length, SocketFlags.None);
if (gotData == 0)
throw new Exception("I swear, this was working before but isn't anymore...");
message = Encoding.ASCII.GetString(buf);
if (message.StartsWith("!!addlist"))
{
message = message.Replace("!!addlist", "");
string userNick = message.Trim();
if(!namesBox.Items.Contains(userNick))
{
addNick(userNick);
}
continue;
}
else if (message.StartsWith("!!removelist"))
{
message = message.Replace("!!removelist", "");
string userNick = message.Trim();
removeNick(userNick);
output("Someone left the room: " + userNick);
continue;
}
output(message);
}
}
catch (Exception)
{
isConnected = false;
output(Environment.NewLine + "Connection to the server lost.");
}
}
public void output(string s)
{
try
{
lock (conLock)
{
chatBox.Text += s + Environment.NewLine;
}
}
catch (Exception) { }
}
private void ChatWindow_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
if(isConnected)
sendRaw("!!removelist " + nickName);
isConnected = false;
clientSocket.Shutdown(SocketShutdown.Receive);
if (chatThread.IsAlive)
chatThread.Abort();
callingForm.Close();
}
catch (Exception) { }
}
private void sendButton_Click(object sender, EventArgs e)
{
if(isConnected)
send(sendBox.Text);
}
private void sendBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (isConnected)
{
if (sendBox.Text != "")
{
send(sendBox.Text);
sendBox.SelectAll();
e.SuppressKeyPress = true;
e.Handled = true;
}
}
}
}
private void send(string t) {
try
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(nickName + ": " + t + "\r\n");
clientSocket.Send(data);
output(nickName + ": " + t);
}
catch (Exception e)
{
displayError(e.ToString());
}
}
private void sendRaw(string t)
{
try
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(t + "\r\n");
clientSocket.Send(data);
}
catch (Exception e)
{
displayError(e.ToString());
}
}
private void chatBox_TextChanged(object sender, EventArgs e)
{
chatBox.SelectionStart = chatBox.Text.Length;
chatBox.ScrollToCaret();
}
private void sendBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
e.SuppressKeyPress = true;
}
}
To do:
Add invokes, more delegates, do some more QA and find out what breaks it.
Also, I believe there's still the possibility of packet loss due to the client addlist functions being in the read loop. I believe this is why the "crappy hack" using Thread.Sleep(10) in the server callback for name population is an issue.
I think it might be better to either pass the command off to another thread while continuing to read or have the client tell the server it's ready for another name.
Otherwise, there might be some data loss during name updates.
The other thing is that, as was said in the comments above, delegates should be used when updating the UI objects (chatbox and listbox). I wrote the code for these but ultimately removed it because there was no noticeable change and I wanted to keep it simple.
I do still use an object lock when outputting text to the chatbox, but there's no noticeable difference there.
The code should be added as not using delegates is potentially problematic, but I literally caught the chat box in an infinite loop of updates without issue.
I tried breaking it with telnet and was successful so I added a newConnection property to the StateObject to ensure that each client can only send "!!addlist" once.
There are, of course, other ways to abuse the server by creating a client that joins and leaves repeatedly, so ultimately I will probably end up passing the !!removelist handling to the server instead of leaving it up to the client.
I've looked around links related. I can't find any. Help me, please.
Here's my code.(VS2010)
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://whatismyipaddress.com/");
request.Proxy = new WebProxy("127.0.0.1:9150");
request.KeepAlive = false;
try
{
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
string temp = reader.ReadToEnd();
MessageBox.Show(temp);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
That brings error message like this.
(501) Not implemented.
And Tor says.
Socks version 71 not recognized.(Tor is not a http proxy)
What's wrong?Someone help me.
Unfortunately after some digging TOR is not a HTTP Proxy. It's a SOCKS proxy, you can use something like Privoxy that allows sock forwarding.
using Tor as Proxy
How to use Privoxy with TOR: http://www.privoxy.org/faq/misc.html#TOR
I created the following class (HttpOverSocksProxy) to route my http requests through to the Tor socks proxy.
It does this by:
listening on a local port (eg 127.0.0.1:9091) for incoming http requests
grabs the host from the headers of these requests
opens up a connection through Tor to this host
copys all data (GET\POST,headers,body) from the source connection through to the Tor connection and visa versa
Http requests are then made as you have done above but with the WebProxy set to the http\socks proxy in the above case this would be 127.0.0.1:9091
Note that https requests are not supported, you will recieve a 400 error from the webserver
I am using the Mentalis class ProxySocket to wrap up the Socks connection as a standard Socket
http://www.mentalis.org/soft/class.qpx?id=9
This code has not being thoroughly tested but so far it works fine.
HttpOverSocksProxy Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using Org.Mentalis.Network.ProxySocket;
using System.IO;
namespace ConsoleApplication1
{
/*
* HTTPS is not supported, it will probably result in a (400) 'Bad Request' response.
*/
public class HttpOverSocksProxy
{
private class Connection
{
public IPLocation host_loc;
public bool host_found = false;
public bool host_connected = false; //if have_found==true && host_connected==false then we are currently connecting to the host
public long host_last_read_pos = 0;
public NetworkStream client_stream = null;
public TcpClient client_tcp = null;
public NetworkStream host_stream = null;
public ProxySocket host_socket = null;
public byte[] client_buf_ary = null;
public byte[] host_buf_ary = null;
public MemoryStream buf_str = null;
public Connection(NetworkStream str,TcpClient client,int buffer_size)
{
this.client_stream = str;
this.client_tcp = client;
this.host_buf_ary = new byte[buffer_size];
this.client_buf_ary = new byte[buffer_size];
this.buf_str = new MemoryStream(buffer_size);
}
}
private struct IPLocation
{
public string host;
public int port;
public IPLocation(string host, int port)
{
this.host = host;
this.port = port;
}
}
private TcpListener _tcp_server;
private List<Connection> _connections = new List<Connection>();
public IPEndPoint EndPoint_Source_Http { get; private set; }
public IPEndPoint EndPoint_Destination_Socks { get; private set; }
public ProxyTypes SocksProxyType { get; private set; }
public int Buffer_Size { get; private set; }
public HttpOverSocksProxy(IPEndPoint http_listen, IPEndPoint socks_proxy, ProxyTypes socks_proxy_type, int buffer_size = 1024*4)
{
this.EndPoint_Source_Http = http_listen;
this.EndPoint_Destination_Socks = socks_proxy;
this.SocksProxyType = socks_proxy_type;
this.Buffer_Size = buffer_size;
}
public void Start()
{
_tcp_server = new TcpListener(EndPoint_Source_Http);
_tcp_server.Start();
_tcp_server.BeginAcceptTcpClient(Client_Accept, _tcp_server);
}
public void Stop()
{
lock (_connections)
{
_tcp_server.Stop();
_connections.ForEach(a => Close(a));
_connections.Clear();
}
}
private void Client_Accept(IAsyncResult result)
{
TcpListener tcp_server = result.AsyncState as TcpListener;
if (tcp_server != null)
{
TcpClient tcp_client = tcp_server.EndAcceptTcpClient(result);
if (tcp_client != null)
{
Connection conn = new Connection(tcp_client.GetStream(), tcp_client, Buffer_Size);
lock (_connections)
{
_connections.Add(conn);
}
conn.client_stream.BeginRead(conn.client_buf_ary, 0, Buffer_Size, Client_Write, conn);
}
tcp_server.BeginAcceptTcpClient(Client_Accept, tcp_server);
}
}
private void Client_Write(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
try
{
int len = conn.client_stream.EndRead(result);
if (len == 0) // Client has closed the connection
{
Close(conn);
}
else
{
lock (conn)
{
if (conn.host_connected)
{
try
{
conn.host_stream.Write(conn.client_buf_ary, 0, len); //we want this to block
}
catch (Exception e_h)
{
if (!Handle_Disposed(e_h, conn))
throw;
}
}
else
conn.buf_str.Write(conn.client_buf_ary, 0, len);
if (!conn.host_found)
OpenHostConnection(conn);
conn.client_stream.BeginRead(conn.client_buf_ary, 0, Buffer_Size, Client_Write, conn);
}
}
}
catch (Exception e_c)
{
if (!Handle_Disposed(e_c, conn))
throw;
}
}
}
private void OpenHostConnection(Connection conn)
{
if (conn.host_found)
throw new Exception("Already have host"); //should never happen
#region Get Host from headers
{
MemoryStream str_mem = conn.buf_str;
str_mem.Position = conn.host_last_read_pos;
string raw_host_line;
while ((raw_host_line = ReadLine(str_mem, ASCIIEncoding.ASCII)) != null)
{
conn.host_last_read_pos = str_mem.Position;
if (raw_host_line.Length == 0)
throw new Exception("Failed to find Host in request headers");
int idx_split;
if ((idx_split = raw_host_line.IndexOf(':')) > 0 && idx_split < raw_host_line.Length)
{
string key = raw_host_line.Substring(0, idx_split);
string val = raw_host_line.Substring(idx_split + 1).Trim();
if (key.Equals("host", StringComparison.InvariantCultureIgnoreCase))
{
string[] host_parts = val.Split(':');
if (host_parts.Length == 1)
{
conn.host_loc = new IPLocation(host_parts[0], 80);
}
else if (host_parts.Length == 2)
{
conn.host_loc = new IPLocation(host_parts[0], Int32.Parse(host_parts[1]));
}
else
throw new Exception(String.Format("Failed to parse HOST from '{0}'", raw_host_line));
conn.host_found = true;
}
}
}
str_mem.Seek(0,SeekOrigin.End);
}
#endregion
#region Open Host Connection
{
if (conn.host_found)
{
try
{
ProxySocket skt = new ProxySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
skt.ProxyEndPoint = EndPoint_Destination_Socks;
skt.ProxyType = ProxyTypes.Socks5;
conn.host_socket = skt;
if (conn.host_loc.port == 443)
Console.WriteLine("HTTPS is not suported.");
skt.BeginConnect(conn.host_loc.host, conn.host_loc.port, Host_Connected, conn);
}
catch (ObjectDisposedException e)
{
if (!Handle_Disposed(e, conn))
throw;
}
}
}
#endregion
}
private void Host_Connected(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
lock (conn) //Need to set up variables and empty buffer, cant have the Client writing to the host stream during this time
{
try
{
conn.host_socket.EndConnect(result);
conn.host_stream = new NetworkStream(conn.host_socket);
conn.host_connected = true;
conn.buf_str.Position = 0;
conn.buf_str.CopyTo(conn.host_stream);
conn.host_stream.BeginRead(conn.host_buf_ary, 0, Buffer_Size, Host_Write, conn);
}
catch (Exception e)
{
if (!Handle_Disposed(e, conn))
throw;
}
}
}
}
private void Host_Write(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
try
{
int len = conn.host_stream.EndRead(result);
if (len == 0)
{
Close(conn);
}
else
{
try
{
conn.client_stream.Write(conn.host_buf_ary, 0, len); //we want this to block
}
catch (Exception e_c)
{
if (!Handle_Disposed(e_c, conn))
throw;
}
conn.host_stream.BeginRead(conn.host_buf_ary, 0, Buffer_Size, Host_Write, conn);
}
}
catch (Exception e_h)
{
if (!Handle_Disposed(e_h, conn))
throw;
}
}
}
private void Close(Connection conn)
{
lock (conn)
{
try
{
if (conn.host_connected)
conn.host_socket.Close();
}
catch { }
try
{
conn.client_tcp.Close();
}
catch { }
}
}
private bool Handle_Disposed(Exception exp,Connection conn)
{
if (exp is ObjectDisposedException || (exp.InnerException != null && exp.InnerException is ObjectDisposedException))
{
Close(conn);
return true;
}
else
return false;
}
private string ReadLine(MemoryStream str,Encoding encoding) // Reads a line terminated by \r\n else returns resets postion and returns null
{
long idxA= str.Position; //first position of line
long idxB =-1; //position after last char
int b_last = str.ReadByte();
int b_this = 0;
for (long i = 1; i < str.Length; i++)
{
b_this = str.ReadByte();
if (b_this == '\n' && b_last == '\r')
{
idxB = str.Position;
str.Position = idxA;
int len = (int)(idxB - idxA);
byte[] buf = new byte[len];
str.Read(buf, 0, len);
return encoding.GetString(buf);
}
else
b_last = b_this;
}
str.Position = idxA;
return null;
}
}
}
Example Usage:
static void Main(string[] args)
{
IPAddress localhost = IPAddress.Parse("127.0.0.1");
IPEndPoint src_http = new IPEndPoint(localhost, 9091);
IPEndPoint des_tor = new IPEndPoint(localhost, 9050);
HttpOverSocksProxy proxy = new HttpOverSocksProxy(src_http, des_tor, ProxyTypes.Socks5);
proxy.Start();
WebClientExt client = new WebClientExt();
client.Proxy = new WebProxy(src_http.ToString(), false);
string res = client.DownloadString("http://en.wikipedia.org/wiki/HTTP_compression");
Console.WriteLine(res);
Console.WriteLine("Done");
Console.ReadKey();
}
I had to make small modifications to the class ProxySocket so that the async calls retuned my state object. Not sure why it didn't already.
I can't post the updated code due to a character limit but I can describe them quickly enough:
In ProxySocket.BeginConnect set this.State = state
In ProxySocket.OnHandShakeComplete set AsyncResult.AsyncState = State.
The property IAsyncProxyResult.AsyncState was updated so the there was a setter with privacy 'internal'
I have one server and client application using socket programming in c#. In this, max. 10 clients can be connected to the server at a time. But my requirement is that I have to block one of the clients via IP address when i'm sending messages through server.. Please help with blocking. The program is given below..
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
namespace Server
{
public partial class SocketServer : Form
{
const int MAX_CLIENTS = 10;
public AsyncCallback pfnWorkerCallBack;
private Socket m_mainSocket;
private Socket[] m_workerSocket = new Socket[10];
private int m_clientCount = 0;
private byte[] byData;
public SocketServer()
{
InitializeComponent();
textBoxIP.Text = GetIP();
}
String GetIP()
{
String strHostName = Dns.GetHostName();
// Find host by name
IPHostEntry iphostentry = Dns.GetHostByName(strHostName);
// Grab the first IP addresses
String IPStr = "";
foreach (IPAddress ipaddress in iphostentry.AddressList)
{
IPStr = ipaddress.ToString();
ip = IPStr;
return IPStr;
}
ip = IPStr;
return IPStr;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void buttonStartListen_Click(object sender, EventArgs e)
{
try
{
// Check the port value
if (textBoxPort.Text == "")
{
MessageBox.Show("Please enter a Port Number");
return;
}
string portStr = textBoxPort.Text;
int port = System.Convert.ToInt32(portStr);
// Create the listening socket...
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
// Bind to local IP Address...
m_mainSocket.Bind(ipLocal);
// Start listening...
m_mainSocket.Listen(4);
// Create the call back for any client connections...
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
UpdateControls(true);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void UpdateControls(bool listening)
{
buttonStartListen.Enabled = !listening;
buttonStopListen.Enabled = listening;
}
public delegate void UpdateTextCallback(string message, object obj);
public void OnClientConnect(IAsyncResult asyn)
{
try
{
// Here we complete/end the BeginAccept() asynchronous call
// by calling EndAccept() - which returns the reference to
// a new Socket object
m_workerSocket[m_clientCount] = m_mainSocket.EndAccept(asyn);
// Let the worker Socket do the further processing for the
// just connected client
WaitForData(m_workerSocket[m_clientCount]);
// Now increment the client count
++m_clientCount;
// Display this client connection as a status message on the GUI
String str = String.Format("Client # {0} connected", m_clientCount);
//textBoxMsg.Text = str;
textBoxMsg.BeginInvoke(new UpdateTextCallback(UpdateText), new object[] { str, textBoxMsg });
// Since the main Socket is now free, it can go back and wait for
// other clients who are attempting to connect
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void UpdateText(string message, object ctrl)
{
if (ctrl is TextBox)
textBoxMsg.Text = message;
if(ctrl is RichTextBox)
richTextBoxReceivedMsg.AppendText(message);
}
public class SocketPacket
{
public System.Net.Sockets.Socket m_currentSocket;
public byte[] dataBuffer = new byte[1];
}
public void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
// Specify the call back function which is to be
// invoked when there is any write activity by the
// connected client
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket();
theSocPkt.m_currentSocket = soc;
// Start receiving any data written by the connected client
// asynchronously
soc.BeginReceive(theSocPkt.dataBuffer, 0,
theSocPkt.dataBuffer.Length,
SocketFlags.None,
pfnWorkerCallBack,
theSocPkt);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0;
// Complete the BeginReceive() asynchronous call by EndReceive() method
// which will return the number of characters written to the stream
// by the client
iRx = socketData.m_currentSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer,
0, iRx, chars, 0);
System.String szData = new System.String(chars);
//richTextBoxReceivedMsg.AppendText(szData);
richTextBoxReceivedMsg.BeginInvoke(new UpdateTextCallback(UpdateText), new object[] { szData, richTextBoxReceivedMsg });
// Continue the waiting for data on the Socket
WaitForData(socketData.m_currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void buttonStopListen_Click(object sender, EventArgs e)
{
CloseSockets();
UpdateControls(false);
}
void CloseSockets()
{
if (m_mainSocket != null)
{
m_mainSocket.Close();
}
for (int i = 0; i < m_clientCount; i++)
{
if (m_workerSocket[i] != null)
{
m_workerSocket[i].Close();
m_workerSocket[i] = null;
}
}
}
private void buttonSendMsg_Click(object sender, EventArgs e)
{
try
{
Object objData = richTextBoxSendMsg.Text;
byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
for (int i = 0; i < m_clientCount; i++)
{
if (m_workerSocket[i] != null)
{
if (m_workerSocket[i].Connected)
{
m_workerSocket[i].Send(byData);
}
}
}
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void Form1_Minimize(object sender, System.EventArgs e)
{
if (FormWindowState.Minimized == WindowState)
{
Hide();
this.notify.Visible = true;
}
}
private void Form1_Resize(object sender, System.EventArgs e)
{
Show();
WindowState = FormWindowState.Normal;
this.notify.Visible = false;
}
This is somewhat easy to do, you just need to look a little more at the client connection routine... Replace the 127.0.0.1 below with the IP address you want to deny and throw an exception or simply close the connection and return.
public void OnClientConnect(IAsyncResult asyn)
{
try
{
TcpListener listener = (TcpListener)ar.AsyncState;
System.Net.Sockets.TcpClient client = listener.EndAcceptTcpClient(ar);
IPEndPoint clientEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
if (clientEndPoint.Address == new IPAddress("127.0.0.1"))
throw new InvalidOperationException();