Government Security
Network Security Resources

Jump to content

Photo

C#: Basic Sockets Question

- - - - - server c# tutorial
  • Please log in to reply
11 replies to this topic

#1 angelsky

angelsky

    Private First Class

  • Members
  • 33 posts

Posted 24 August 2005 - 02:06 AM

I started yesterday digging into sockets in c#, I found a tutorial and based on that I develloped a basic one-way chat program.
It doesn't do alot, client types messages, server receives them and shows them on a screen.
Now I was thinking about making it a 2 way communication thingy. But I guess a socket can only be listening or sending, not both at the same time?
If this is correct this means that I need to set-up 2 sockets on both client and server (wich will logicaly be no longer server as both programs will just be server and client).

Is this correct or am I thinking in the wrong way?

#2 usch

usch

    Staff Sergeant

  • Sergeant Major
  • 269 posts

Posted 24 August 2005 - 05:14 AM

http://www.codeguru....icle.php/c7695/

but in general, yeah u have to open a second connection in a second thread to gain the funcionality.

cheers
usch

#3 angelsky

angelsky

    Private First Class

  • Members
  • 33 posts

Posted 25 August 2005 - 02:52 AM

Thx alot,

though i'm gonna have to filter out the grafical stuff.
I wanna make a cmdline based chat program.
After this succeeded i wanna make it a bot-like program, client gives orders, bot does what asked.

I'll see where i get :)

If i have anymore questions, i'll be posting them here!!

thx again for quick reply!!

#4 0X86F4

0X86F4

    Private First Class

  • Members
  • 41 posts

Posted 25 August 2005 - 04:14 AM

You can use System.Net.Sockets.TcpClient for that purpose. Have a look at the documentation and examples.

You dont need to open another connection. You can read and/or write the network stream with one connection.

You can start with this first: TCP Chat example

Unless you are planning to make a chatbot, eggdrop whatever, making a chat client commandline can be tough for you, because of the effort you ll spend to develop a commandline gui.

#5 angelsky

angelsky

    Private First Class

  • Members
  • 33 posts

Posted 25 August 2005 - 04:27 AM

I have seen this example, and i am using it already.
But as i said, i wan't to make it commandline based.

I know its gonna be tough but i like a challenge and i can only learn :)

Thx to search and for the other info!

#6 angelsky

angelsky

    Private First Class

  • Members
  • 33 posts

Posted 25 August 2005 - 07:08 AM

Just done coding the 'interface'
works a bit like msn, when window aint full, messages remain on screen, once window is to small, the oldest messages dissapear and the newer once take there place.

This is just coded with my one way chat client, now i got to code it 2 way communication.

will post progress as soon as it does progress :P

Posted Image

Posted Image

I don't think this is bad for 3 days of experience with sockets :)

Edit:
Well i figured how to send and receive at the same time, indeed no problem with one connection.

Though i'm screwed by the fact that i automaticaly wait for user input to be sended, so my entire program has to wait on the Console.readLine().

i could work this problem out by not setting a readline, but how could i make clear that i want to type a message then?

anyone idea's?

#7 aapje

aapje

    Staff Sergeant

  • Members
  • 289 posts

Posted 26 August 2005 - 01:31 PM

use threads for the sockets

#8 Zimmergren

Zimmergren

    Staff Sergeant

  • Sergeant Major
  • 487 posts

Posted 26 August 2005 - 04:50 PM

Exactly, use threading to execute the different commands, which will allow the application to stay "unlocked".

If you need any assistance just let us know.
I coded QIM in C# (Just like ICQ, but without filetransfer)
http://www.zimmergren.net

Formerly known as t0bban.

#9 angelsky

angelsky

    Private First Class

  • Members
  • 33 posts

Posted 27 August 2005 - 03:20 AM

Well, did some reading, got threading to work in simple examples.
In the way i wanted to use it at first that didn't work.
i wanted to start a thread and give it some parameters, seems you can't pass any parameters to a new thread.
ok, went to google, did some research and i ended up at this
they are talking about thread local storage. the local in this name already gave me the creeps cause i wanted to be able to alter some of the parameters (they were meant to be passed as out parameters).

I'll explain why:
as you could see i had an interface, i made it pretty easy.
it's an array of 16 elements and i update them if the array is full so that messages scroll up and you can read the new ones.
for this i have a variable index, to know wich element of the array has to be filled, the array messages, to know the past messages and a variable tcpclnt wich makes sure i can read/write with the stream.

if i receive a message i have to put it in the array messages at the index 'index'.
but after this, i have to increase index by so that i wouldn't overwrite it the next time

when i was reading the text at the link above, i got the idea that it is possible but i just understand crap of the entire text :P

here i'll post a my code of the client, so you can see how it is that i wanted it to work (it doesn't cause i can't pass no parameters along with the thread):
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using xCon;


public class clnt {

	public static void Main() {
 †
 †try {
 †	TcpClient tcpclnt = new TcpClient();
 †	xConsole.Title = "Chat client (c)Written by angelsky";
 †	Console.WriteLine("Verbinden...");
 †	/*
 †	Console.WriteLine("Geef het ip-adres in:");
 †	IPAddress ip = IPAddress.Parse(Console.ReadLine());

 †	Console.WriteLine("Geef de poort in:");
 †	int poort = int.Parse(Console.ReadLine());
 †	
 †	tcpclnt.Connect(ip,poort);
 †	*/
 †	IPAddress ip=IPAddress.Parse("192.168.0.2");
 †	int poort = 5555;
 †	tcpclnt.Connect(ip,poort);

 †	//creŽer array om verstuurde + ontvangen berichten in te bewaren
 †	string[] berichten = new string[16];

 †	//definieer wanneer gestopt moet worden
 †	bool stoppen;
 †	int index=0;

 †	//start de 2e thread
 †	Thread t = new Thread(new ThreadStart(luisteren(berichten, out index, tcpclnt)));
 †	t.Start();

 †	do{
 † †schrijfScherm(ip, poort, berichten, index);
 † †arrayControleren(berichten, index);
 † †verstuur(tcpclnt, ip, berichten, index, out stoppen);
 † †if(index<berichten.GetLength(0)-1){
 † †	index++;
 † †	if(index==berichten.GetLength(0)-1){
 † † †schrijfScherm(ip, poort, berichten, index);
 † † †verstuur(tcpclnt, ip, berichten, index, out stoppen);
 † †	}
 † †}
 †	}while(stoppen == false);

 †	t.Join();
 †	tcpclnt.Close();
 †}
 †catch (Exception e) {
 †	Console.WriteLine("Error..... " + e.StackTrace);
 †}
	}/*STOP MAIN*/
	static void arrayControleren(string[] berichten, int index){
 †if(index==berichten.GetLength(0)-1){
 †	for(int i=0; i<berichten.GetLength(0)-1; i++){
 † †berichten[i]=berichten[i+1];
 †	}
 †}
	}/*STOP ARRAYCONTROLEREN*/
	static void verstuur(TcpClient tcpclnt, IPAddress ip, string[] berichten, int index, out bool stoppen){
 †String bericht=Console.ReadLine();
 †Stream stm = tcpclnt.GetStream();
 † † †
 †ASCIIEncoding asen= new ASCIIEncoding();
 †byte[] ba=asen.GetBytes(bericht);

 †string arrayBericht = "Verstuurd naar "+ip+":"+bericht;
 †berichten[index] = arrayBericht;
 †
 †stm.Write(ba,0,ba.Length);

 †if(bericht=="stop"){
 †	stoppen=true;
 †}else{
 †	stoppen=false;
 †}
	}/*STOP VERSTUUR*/
	static void schrijfScherm(IPAddress ip, int poort, string[] berichten, int index){
 †xConsole.ClearScreen();
 †Console.Write("--------------------+--------------------------------------+--------------------");
 †Console.Write(" † † † † † † † † † †| †Verbonden met server: "+ip+" † ");
 †Console.WriteLine("|");
 †Console.Write(" † † † † † † † † † †| †Verbonden op poort: † "+poort+" † † † † †");
 †Console.WriteLine("|");
 †Console.WriteLine("--------------------+--------------------------------------+--------------------");
 †for(int i=0; i<=16; i++){
 †	if(i<=index){
 † †Console.WriteLine("{0}", berichten[i]);
 †	}else{
 † †Console.WriteLine("");
 †	}
 †}
 †Console.Write("--------------------------------------------------------------------------------");
 †Console.Write("versturen: ");
	}/*STOP SCHRIJFSCHERM*/
	static void luisteren(string[] berichten, out int index, TcpClient tcpclnt) {
 †string bericht = "Ontvangen van test: ";
 †Stream stm = tcpclnt.GetStream();
 †byte[] bb=new byte[100];
 †int k=stm.Read(bb,0,100);
 †	
 †for (int i=0;i<k;i++){
 †	bericht = bericht + Convert.ToString(bb[i]);
 †}
 †berichten[index] = bericht;
 †if(index<berichten.GetLength(0)-1){
 †	index=index+1;
 †}else{
 †	index=index;
 †}
	}/*STOP LUISTEREN*/
}

don't know if any of you have suggestions on fixing this?
or know to explain me the thread local storage

this is the problem cause this is what has to be called in the new thread:
static void luisteren(string[] berichten, out int index, TcpClient tcpclnt) {
 string bericht = "Ontvangen van test: ";
 Stream stm = tcpclnt.GetStream();
 byte[] bb=new byte[100];
 int k=stm.Read(bb,0,100);
 †
 for (int i=0;i<k;i++){
 †bericht = bericht + Convert.ToString(bb[i]);
 }
 berichten[index] = bericht;
 if(index<berichten.GetLength(0)-1){
  index=index+1;
 }else{
  index=index;
 }
 }

thx on advance

ps: sorry that vars are in dutch :$

#10 usch

usch

    Staff Sergeant

  • Sergeant Major
  • 269 posts

Posted 27 August 2005 - 08:31 AM

i have searched on some different forums for the problem and found something telling to use a method called Invoke(), but i haven't really understood its usage. haven't dealt much with threads yet ;) .
but what you could do to give a thread parameters is to let the thread have its own class. i know that it is not the most proper way to accomplish but i dont care ;).

you could then give the parameters to the class' constructor.
public class TheThread
{
private string param1;
private int param2;

    public static void TheThread(string parameter1,int parameter2)
param1=parameter1;
param2=parameter2;

{
Thread thread = new Thread(new ThreadStart(blaaa));
//some more for the thread
}

void blaaa()
{
Console.WriteLine(param1);
//something with the other parameters
}
}

yeah should be something like that ^^. you could also give the thread's class public variables, which are changed by the class which calls the thread, but that is called bad style ;)


usch

#11 aapje

aapje

    Staff Sergeant

  • Members
  • 289 posts

Posted 28 August 2005 - 08:30 AM

Yes, you should make a seperate thread class, when you create the class let it set the connection stuff etc and then create the thread.
Also you can better use ArrayList, its much easier.

#12 A2_

A2_

    Private First Class

  • Members
  • 34 posts

Posted 28 August 2005 - 08:54 AM

Yes, you should make a seperate thread class, when you create the class let it set the connection stuff etc and then create the thread.
Also you can better use ArrayList, its much easier.

<{POST_SNAPBACK}>


not just for this example, the vast majority of cases where you'll want to create seperate threads in .net will be best executed with their own classes..





Also tagged with one or more of these keywords: server, c#, tutorial