📄 tcpudpclient.cs
字号:
/* File : TcpUdpClient.cs
* Namespace : ClientServer
* Classes : TcpUdpClient
*/
namespace ClientServer
{
/* Class : TcpUdpClient
* Base Class : None
* Functionality : Handles all the client side functionalities including:
* 1. Creates a TcpClient to be used during the chat session;
* 2. Creates a UdpClient to send all the call initiation messages like
* NOTIFY REQUEST and NOTIFY HANGUP REQUEST.
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.Timers;
public class TcpUdpClient
{
private NetworkStream tcpStream;
private UdpClient udpNotifyClient;
private System.Timers.Timer notifyTimer;
public TcpClient tcpClient;
public TcpUdpClient()
{
}
/* Function : createTcpClientConnection(String serverName)
* Purpose : This function will create a TCP connection to the given serverName and
* the well known TCP Port (4567).
* Algorithm : It creates a TcpClient instance to the serverName and SAMPLETCPPORT,
* set the LingerOption. It also assigns a TCP stream to tcpStream so that
* the TcpClient can use to send data later on.
*/
public void createTcpClientConnection(String serverName)
{
try
{
//Create an instance of TcpClient.
tcpClient = new TcpClient(serverName, ClientServerConstants.SAMPLETCPPORT);
//Make sure the TcpClient will be closed right away when TcpClient.Close() is called.
LingerOption tcpClientLingerOption = new LingerOption(false,0);
tcpClient.LingerState = tcpClientLingerOption;
//Get the NetworkStream for this tcpClient instance.
tcpStream = tcpClient.GetStream();
}
catch (Exception e)
{
MessageBox.Show("An Exception has occurred!" + e.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
/* Function : tcpClientSendMessage(String whatEver)
* Purpose : This function will send a message "whatEver" using the tcpStream.
* Algorithm : The tcpstream is assigned from the createTcpClientConnection()
* function. First, it makes sure whether the tcpStream is writable.
* if so, it converts the whatEver string to a byte array by
* System.Text.Encoding.ASCII.GetBytes(whatEver.ToCharArray()). After
* that, it flushes the byte array to the tcpStream.
*/
public void tcpClientSendMessage(String whatEver)
{
try
{
if (tcpStream.CanWrite)
{
Byte[] inputToBeSent = System.Text.Encoding.ASCII.GetBytes(whatEver.ToCharArray());
tcpStream.Write(inputToBeSent, 0, inputToBeSent.Length);
tcpStream.Flush();
}
}
catch (SocketException se)
{
MessageBox.Show("A Socket Exception has occurred!" + se.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
/* Function : tcpClientSendMessage(String whatEver)
* Purpose : This function will simply close the tcpClient.
*
*/
public void closeTcpClientConnection()
{
try
{
tcpClient.Close();
}
catch (SocketException se)
{
MessageBox.Show("A Socket Exception has occurred!" + se.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
/* Function : sendNotify(String serverName, String eventToNotify)
* Return : boolean
* Purpose : This function will send a notification message to the UDP server
* at "serverName" and the UDP well known port (UDPNOTIFYPORT).
* Algorithm : This function first creates a UdpClient instance (udpNotifyClient)
* that will send the string "eventToNotify" to "serverName" and the
* well known port(UDPNOTIFYPORT). It will then wait for the response
* returned by the remote peer.
* According to the response received from the remote peer, this function
* will take different action:
*
* 1. If the remote peer accepts the call request, the function will
* return true and the chat session can begin.
* 2. If the "eventToNotify" is notifyHangupRequest, and the response is
* notifyHangupAccept, the function will return true and the chat
* session will terminate gracefully.
* 3. Any other response prompts the function to return false.
*
* As soon as the "eventToNotify" is sent, a 30 seconds Notify Timer
* will be started. This timer is used to make sure that the tcpClient
* will get a response from the remote peer (whether he/she wants to chat
* or not) within 30 seconds. If the timer expires, a MessageBox will pop
* up to notify the local user that the remote peer did not respond
* promptly. When it receives a response from the remote peer, the timer
* will be stopped.
*
*/
public bool sendNotify(String serverName, String eventToNotify)
{
Byte[] receivedNotify = new Byte[64];
try
{
//Create an instance of UdpClient.
udpNotifyClient = new UdpClient(serverName, ClientServerConstants.UDPNOTIFYPORT);
Byte[] inputToBeSent = new Byte[64];
//Convert the "eventToNotify" string to a byte array, and then send it to
//the remote UDP server using udpNotifyClient.
inputToBeSent = System.Text.Encoding.ASCII.GetBytes(eventToNotify.ToCharArray());
int nBytesSent = udpNotifyClient.Send(inputToBeSent, inputToBeSent.Length);
//Start the Notify Timer to make sure that the remote peer will respond within
//a 30 seconds time frame.
this.startNotifyTimer();
IPHostEntry remoteNotifyHostEntry = Dns.GetHostByName(serverName);
IPEndPoint remoteNotifyIpEndPoint = new IPEndPoint(remoteNotifyHostEntry.AddressList[0],
ClientServerConstants.UDPNOTIFYPORT);
//Call Receive() to "wait" for the remote peer's response. As soon as the response
//is received, stop the timer.
receivedNotify = udpNotifyClient.Receive(ref remoteNotifyIpEndPoint);
//There is a known issue here. After the timer expires, the udpNotifyClient will be
//closed. This will prompt an exception message to pop up because the socket that
//the udpNotifyClient is bound on will be closed too. However, this won't affect the
//program in anyway.
this.stopNotifyTimer();
}
catch (SocketException se)
{
if (se.ErrorCode == 11004)
{
MessageBox.Show("Unknown host. Please check the hostname or IP address and try again.",
"WinChat", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
//ErrorCode 10054 corresponds to the exception: An existing connection is forcibly
//closed by the remote host. This happens when the remote host does not have
//WinChat for .Net running. This exception shouldn't stop the processing.
if ((se.ErrorCode != 10054) && (se.ErrorCode != 10038))
{
MessageBox.Show("A Socket Exception has occurred!" + se.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
catch (Exception e)
{
MessageBox.Show("An Exception has occurred!" + e.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
String dataReceivedNotify = System.Text.Encoding.ASCII.GetString(receivedNotify);
switch (dataReceivedNotify)
{
case ClientServerConstants.notifyAccept:
{
//The remote peer accepts the call request. The chat session can now begin.
MessageBox.Show("The other party accepted your call request. You can start talking now.",
"WinChat", MessageBoxButtons.OK);
return true;
}
case ClientServerConstants.notifyUnknownReject:
{
//The response from the remote peer is not recognized as one of the possible response.
//The chat session cannot begin.
MessageBox.Show("There was some network problem. Please try again.", "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
case ClientServerConstants.notifyReject:
{
//The remote peer rejects the call request. The chat session cannot begin.
MessageBox.Show("The party your are calling rejects your call.", "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
case ClientServerConstants.notifyHangupAccept:
{
//The notifyHangupAccept would only be received when the eventToNotify was
//notifyHangupRequest. If not, some data might have been lost in the network.
if (eventToNotify.Equals(ClientServerConstants.notifyHangupRequest))
return true;
else
return false;
}
case ClientServerConstants.notifyAlreadyTalking:
{
//The remote peer is in 'alreadyTalking" mode. The chat session cannot begin.
MessageBox.Show("The party you are calling is busy at this moment.", "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
default:
{
return false;
}
}
}
/* Function : startNotifyTimer()
* Return : void
* Purpose : This function will start the Notify Timer.
*/
public void startNotifyTimer()
{
// Create a new Timer with Interval set to 20 seconds.
notifyTimer = new System.Timers.Timer(ClientServerConstants.UDPTIMER);
notifyTimer.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);
// Only raise the event the first time Interval elapses.
notifyTimer.AutoReset = false;
notifyTimer.Enabled = true;
}
/* Function : stopNotifyTimer()
* Return : void
* Purpose : This function sill stop the Notify Timer.
*/
public void stopNotifyTimer()
{
notifyTimer.Stop();
}
/* Function : OnTimedEvent(object source, ElapsedEventArgs e)
* Return : void
* Purpose : This function sill close the udpNotifyClient when the Notify
* Timer expires.
*/
public void OnTimedEvent(object source, ElapsedEventArgs e)
{
try
{
MessageBox.Show("The party you are calling does not respond.", "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
udpNotifyClient.Close();
}
catch (Exception ex)
{
MessageBox.Show("An Exception has occurred!" + ex.ToString(), "WinChat",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
}
// created on 8/26/2001 at 1:21 PM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -