Need help with the Socket Program using Visual C # (Dot Net Framework 4.0)?

Recently I was given a task ...

"To develop a Windows Forms application that can be installed on different Windows machines in the office or in the enterprise. There will be a database on only one machine (ALPHA machine). This database will be used by applications on other beta machines to access data. Application it would be possible to verify whether it is an alpha version or a beta version (does it have a database file with it?) and, therefore, should act as a server or client. "

I can do everything except network requirements and interoperability between applications. So, I started learning Socket Programming over the Internet, and I went through this link ...

The idea I'm working on is ...

  • For the client to send a message to the server.
  • That the server accepted this message and queued this message.
  • Read the message to get the IP address of the client and its request for data.
  • Apply this query in the database and get the result.
  • Convert result to string.
  • Send it to the requesting client.

I can follow steps 3,4 and 5. I am stuck on 1, 2 and 6.

To that...

I created a function for the server, as well as for a client that returns sockets when called. I am creating a separate function because I like my code to be clean, tidy and clear in a few years.

Check out my code below ...

For the server ...

private Socket GetServerReady() { IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Any, 8000); Socket newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); newSock.Connect(RemoteEP); newSock.Listen(10); return (newSock); } 

You will notice that there is no Accept () method anywhere, this is because I want to call it, as shown below, for future reference ...

 Socket CltSock = GetServerReady().Accept(); 

Customer Code ...

 private Socket GetClientReady() { IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Parse(txtBxHost2.Text.Trim()), 8000); Socket ServerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ServerSock.Connect(RemoteEP); return (ServerSock); } 

Finally, the questions .......

  • "Where is the appropriate place to call the functions I wrote above?"

  • "Should I call the Server and Client function in the Form_Load () event?"

  • "What should be the next step towards my main intention, which is indicated in paragraphs 1.2 and 6?"

I do not expect complete code that I can simply copy as it is. Only the right procedure and a little detail over this concept.

I would use only one PC for testing. In addition, another limitation: they will all be encoded in one application. I do not want to write two separate applications for the client and server.

I hope I understand what you understand.

Thanks a lot.

Waiting for an answer.

+4
source share
1 answer

I struggled to achieve a result and somehow managed to find a solution.

Below is my solution:

Server Code: (I put this code in a function that completes execution if any exception is caught)

 private void Looper() { int i = 0; int AttemptCount = 1; while (i == 0) { try { TcpListener tL = new TcpListener(Network.GetLocalIPAddress(), 56009); tL.Start(10); Socket tS = tL.AcceptSocket(); if (tS.Connected) { NetworkStream nS = new NetworkStream(tS); StreamReader Reader = new StreamReader(nS); Output = Reader.ReadToEnd().Trim(); Reader.Close(); nS.Close(); tS.Close(); tL.Stop(); //If Done, End Execution i = 1; } else { MessageBox.Show("The connection to the client is broken or failed..!!\n\nPlease check connection and try again.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error); } } catch (SystemException ex) { //If Not, Loop Execution Again if (MessageBox.Show("Exception: " + ex.Message + "\n\nAttempt Count: " + AttemptCount + "\n\nDo you want to terminate the transmission?", "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes) { i = 1; ResetTimer.Stop(); } else { i = 0; AttemptCount++; } } } } 

When the function above is called, the server waits for any incoming socket to be received. If there is any error somewhere due to reusing a port or something else, it loops and resets the server. (Thus, we do not need to manually call the server function again and again.)

As soon as the server accepts any incoming socket, execution succeeds. For a long time we do not want to continue to refer to the server even after a successful reception. So, instead of calling this function the click_event button, I called it with the Tick_Event timer. Thus, human need is eliminated on the server side.

This leads to a problem. As soon as the server starts to wait to accept it, it is in lock mode. It hangs all processes and controls in a single thread. So, I transferred the function call above to the BackgroundWorker event "Do_Work".

Check below code:

 private void GetServerReady() { if (!bW.IsBusy) { bW.RunWorkerAsync(); txtBxHistory.Text += "\r\n" + Output; } } private void bW_DoWork(object sender, DoWorkEventArgs e) { Looper(); } private void ResetTimer_Tick(object sender, EventArgs e) { GetServerReady(); } 
  • "bW" - "BackgroundWorker".
  • "Inference" is a variable I defined globally.

The reason we need a variable is because

BackgroundWorker has its own thread for executing code placed in its Do_Work event. Thus, the TextBox from our application stream cannot be used by BackgroundWorker to store the received output. Executing this variable and then setting the TextBox Text property of this variable does the trick.

Client Code:

 private void btnSend_Click(object sender, EventArgs e) { TcpClient socketForServer; try { socketForServer = new TcpClient(txtBxDestIP.Text.Trim(), 56009); } catch { MessageBox.Show("Failed to connect to server at " + txtBxDestIP.Text.Trim() + ":999", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } NetworkStream networkStream = socketForServer.GetStream(); StreamWriter streamWriter = new System.IO.StreamWriter(networkStream); try { string InputString; InputString = Network.GetLocalIPAddress() + ": " + txtBxData.Text; streamWriter.Write(InputString); streamWriter.Flush(); socketForServer.Close(); txtBxHistory.Text += "\r\nMe: " + txtBxData.Text.Trim(); txtBxData.Clear(); } catch { MessageBox.Show("Exception reading from Server.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } streamWriter.Close(); networkStream.Close(); socketForServer.Close(); } 
  • "txtBxDestIP" is a TextBox that has the destination IP address as text.
  • "txtBxData" is the text field in which the text will be sent.

This code works flawlessly for me. With the solution above, I can achieve all my motives from step 1 to 6 (mentioned in the question above).

I hope this helps others too. Please suggest if there is a better and more effective way to accomplish this.

Thanks. Best wishes.

+1
source

Source: https://habr.com/ru/post/1482526/


All Articles