Anyone of you know what is the type of service to check the credit balance for the modem using *[number]# ?
I am trying to check balance by using this code.
public AutoResetEvent receiveNow;
public string CheckBalance(SerialPort port)
{
string balance = string.Empty;
try
{
#region Execute Command
//string recievedData = SendATCommand(port, "AT", 300, "No phone connected at ");
string recievedData = SendATCommand(port, "AT", 300, "No phone connected at ");
recievedData = SendATCommand(port, "AT+CMGF=1", 300, "Failed to set message format.");
String command = #"AT+CUSD=1,""*121#"",15";
recievedData = SendATCommand(port, command, 5000, "Failed to count SMS message");
balance = recievedData;
#endregion
}
catch (Exception ex)
{
ErrorLog(ex.Message);
}
return balance;
}
public string SendATCommand(SerialPort port, string command, int responseTimeout, string errorMessage)
{
string input = string.Empty;
try
{
port.DiscardOutBuffer();
port.DiscardInBuffer();
receiveNow.Reset();
port.Write(command + "\r");
input = ReadResponse(port, responseTimeout);
if ((input.Length == 0) || ((!input.EndsWith("\r\n> ")) && (!input.EndsWith("\r\nOK\r\n"))))
ErrorLog("No success message was received.");
}
catch (Exception ex)
{
ErrorLog(ex.Message);
}
return input;
}
public string ReadResponse(SerialPort port, int timeout)
{
string serialPortData = string.Empty;
try
{
do
{
if (receiveNow.WaitOne(timeout, false))
{
string data = port.ReadExisting();
serialPortData += data;
}
else
{
if (serialPortData.Length > 0)
ErrorLog("Response received is incomplete.");
else
ErrorLog("No data received from phone.");
}
}
while (!serialPortData.EndsWith("\r\nOK\r\n") && !serialPortData.EndsWith("\r\n> ") && !serialPortData.EndsWith("\r\nERROR\r\n"));
}
catch (Exception ex)
{
ErrorLog(ex.Message);
}
return serialPortData;
}
first two exec command returns ok,but the third exec command returns error.
USSD code is working from providers mobile partner application,
what sets of AT command do i need to send to handle ussd application properly?
Related
public class GSMModemConnection
{
I made a windows service for receiving SMS I'm using Wavecom Gsm modem 1306B. But after some second I got an
Exception: No data received from phone. I have searched in StackOverflow I found this link Exception: No data received from phone
someone pointed about to create a retry mechanism but I don't know how to implement it.
static void Main(string[] args)
{
GSMModemConnection gsm = new GSMModemConnection();
var result = gsm.OpenPort();
Console.WriteLine(result.PortName);
while (true)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
ShortMessage execResult = gsm.ReadSMS(result, "AT+CMGL=\"ALL\"");
Console.WriteLine(execResult.Message);
Console.WriteLine(execResult.Status);
}
}
public class GSMModemConnection
{
public AutoResetEvent receiveNow;
//string strPortName, string strBaudRate
public SerialPort OpenPort()
{
receiveNow = new AutoResetEvent(false);
SerialPort port = new SerialPort();
port.PortName = "COM3";
port.BaudRate = 115200 /*Convert.ToInt32(strBaudRate)*/; //updated by Anila (9600)
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReadTimeout = 300;
port.WriteTimeout = 300;
port.Encoding = Encoding.GetEncoding("iso-8859-1");
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
port.DtrEnable = true;
port.RtsEnable = true;
return port;
}
//Close Port
public void ClosePort(SerialPort port)
{
port.Close();
port.DataReceived -= new SerialDataReceivedEventHandler(port_DataReceived);
port = null;
}
//Execute AT Command
public string ExecCommand(SerialPort port, string command, int responseTimeout, string errorMessage)
{
try
{
//receiveNow = new AutoResetEvent();
port.DiscardOutBuffer();
port.DiscardInBuffer();
receiveNow.Reset();
port.Write(command + "\r");
//Thread.Sleep(3000); //3 seconds
string input = ReadResponse(port, responseTimeout);
if ((input.Length == 0) || ((!input.EndsWith("\r\n> ")) && (!input.EndsWith("\r\nOK\r\n"))))
throw new ApplicationException("No success message was received.");
return input;
}
catch (Exception ex)
{
throw new ApplicationException(errorMessage, ex);
}
}
//Receive data from port
public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
receiveNow.Set();
}
public string ReadResponse(SerialPort port, int timeout)
{
string buffer = string.Empty;
do
{
if (receiveNow.WaitOne(timeout, false))
{
string t = port.ReadExisting();
buffer += t;
}
else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}
}
while (!buffer.EndsWith("\r\nOK\r\n") && !buffer.EndsWith("\r\n> ") && !buffer.EndsWith("\r\nERROR\r\n"));
return buffer;
}
public ShortMessage ReadSMS(SerialPort port, string p_strCommand)
{
// Set up the phone and read the messages
ShortMessage messages = null;
try
{
#region Execute Command
// Check connection
var a = ExecCommand(port, "AT", 300, "No phone connected");
// Use message format "Text mode"
var b = ExecCommand(port, "AT+CMGF=1\r", 300, "Failed to set message format.");
// Use character set "PCCP437"
//var c = ExecCommand(port, "AT+CSCS=\"PCCP437\"", 300, "Failed to set character set.");
// Select SIM storage
//var d = ExecCommand(port, "AT+CPMS=\"SM\"", 300, "Failed to select message storage.");
// Read the messages
string input = ExecCommand(port, p_strCommand, 5000, "Failed to read the messages.");
#endregion
#region Parse messages
messages = ParseMessages(input);
#endregion
}
catch (Exception ex)
{
throw ex;
}
if (messages != null)
return messages;
else
return null;
}
public ShortMessage ParseMessages(string input)
{
ShortMessage msg = new ShortMessage();
//ShortMessageCollection messages = new ShortMessageCollection();
try
{
Regex r = new Regex(#"\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\r\n(.+)\r\n");
Match m = r.Match(input);
while (m.Success)
{
//msg.Index = int.Parse(m.Groups[1].Value);
msg.Index = int.Parse(m.Groups[1].Value);
msg.Status = m.Groups[2].Value;
msg.Sender = m.Groups[3].Value;
msg.Alphabet = m.Groups[4].Value;
msg.Sent = m.Groups[5].Value;
msg.Message = m.Groups[6].Value;
//messages.Add(msg);
m = m.NextMatch();
}
}
catch (Exception ex)
{
throw ex;
}
return msg;
}
}
You DO have a retry mechanism in place with the DO-WHILE loop from the following expression:
public string ReadResponse(SerialPort port, int timeout)
{
string buffer = string.Empty;
do
{
if (receiveNow.WaitOne(timeout, false))
{
string t = port.ReadExisting();
buffer += t;
}
else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}
}
while (!buffer.EndsWith("\r\nOK\r\n") && !buffer.EndsWith("\r\n> ") && !buffer.EndsWith("\r\nERROR\r\n"));
return buffer;
}
What you can do is reduce the granularity of the error report mechanism.
In this case, for example, the line throw new ApplicationException() will break the loop and get captured in the Exec() function, then thrown again. If you just want to wait for the loop to close and the DO-WHILE loop to get executed, I would replace the following part of the code:
else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}
With:
else
{
if (buffer.Length > 0)
bufferError += "Response received is incomplete.\n";
else
bufferError += "No data received from phone.\n";
}
Why?
After the DO-WHILE loop, the buffer will either return string.Empty or some value.
Up in the code, you have:
string input = ReadResponse(port, responseTimeout);
if ((input.Length == 0) || ((!input.EndsWith("\r\n> ")) && (!input.EndsWith("\r\nOK\r\n"))))
throw new ApplicationException("No success message was received.");
return input;
Basically, if the returned buffer is string.Empty an Exception will be thrown again.
By returning the buffer Error, you can decide later how you want to handle it but the DO-WHILE loop will run at least once up until the condition from the WHILE expression is met.
Rest of the code should look like this:
//Thread.Sleep(3000); //3 seconds
string bufferErrors = string.Empty;
string input = ReadResponse(port, responseTimeout, bufferErrors);
if ((input.Length == 0) || ((!input.EndsWith("\r\n> ")) && (!input.EndsWith("\r\nOK\r\n"))))
throw new ApplicationException("No success message was received.");
if (!string.IsNullOrWhiteSpace(bufferErrors))
{
//Handle bufferErrors
}
return input;
Remember to declare the out parameter in ReadResponse
public string ReadResponse(SerialPort port, int timeout, out string bufferError)
{
string buffer = string.Empty;
bufferError = string.Empty;
Below is one method that basically sends the data to TCP Server.
UPDATE BEGINS HERE:
//////////////////////////////////
private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format)
{
// BT_Code: For the purpose of this sample, this function converts only UInt32 and
// UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them.
byte[] data;
CryptographicBuffer.CopyToByteArray(buffer, out data);
if (format != null)
{
if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4)
{
return BitConverter.ToInt32(data, 0).ToString();
}
else if (format.FormatType == GattPresentationFormatTypes.Utf8)
{
try
{
return Encoding.UTF8.GetString(data);
}
catch (ArgumentException)
{
return "(error: Invalid UTF-8 string)";
}
}
else
{
// Add support for other format types as needed.
return "Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer);
}
}
else if (data != null)
{
// We don't know what format to use. Let's try some well-known profiles, or default back to UTF-8.
if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement))
{
try
{
///////LOOK HERE/////
**string b = ParseHeartRateValue(data).ToString();
TrySend(b);
//return "Heart Rate: " + ParseHeartRateValue(data).ToString();
return "Heart Rate: " + b;**
}
catch (ArgumentException)
{
return "Heart Rate: (unable to parse)";
}
}
else if (selectedCharacteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel))
{
try
{
// battery level is encoded as a percentage value in the first byte according to
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml
return "Battery Level: " + data[0].ToString() + "%";
}
catch (ArgumentException)
{
return "Battery Level: (unable to parse)";
}
}
// This is our custom calc service Result UUID. Format it like an Int
else if (selectedCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid))
{
return BitConverter.ToInt32(data, 0).ToString();
}
// No guarantees on if a characteristic is registered for notifications.
else if (registeredCharacteristic != null)
{
// This is our custom calc service Result UUID. Format it like an Int
if (registeredCharacteristic.Uuid.Equals(Constants.ResultCharacteristicUuid))
{
return BitConverter.ToInt32(data, 0).ToString();
}
}
else
{
try
{
return "Unknown format: " + Encoding.UTF8.GetString(data);
}
catch (ArgumentException)
{
return "Unknown format";
}
}
}
else
{
return "Empty data received";
}
return "Unknown format";
}
///////// END OF UPDATE //////
private async void TrySend(string data)
{
// Create the StreamSocket and establish a connection to the echo server.
StreamSocket socket = new StreamSocket();
try
{
var streamSocket = new Windows.Networking.Sockets.StreamSocket();
{
//The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
var hostName = new Windows.Networking.HostName("127.0.0.1");
await streamSocket.ConnectAsync((new Windows.Networking.HostName("127.0.0.1")), "9999");
// Send a request to the echo server.
using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
while (true)
{
await streamWriter.WriteLineAsync(data);
await streamWriter.FlushAsync();
}
//await streamWriter.WriteLineAsync(data);
//await streamWriter.FlushAsync();
}
}
}
}
catch (Exception)
{
}
}
And here is my TCP Server code that receives the data:
public class EchoServer {
public static void Main() {
TcpListener listener = null;
try
{
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 9999);
listener.Start();
Console.WriteLine("TCP Server Has Started....");
while (true)
{
Console.WriteLine(" ");
Console.WriteLine("Waiting for incoming client connections....");
Console.WriteLine(" ");
Console.WriteLine("A message will display below once the client starts and establishes a connection ");
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine(" ");
Console.WriteLine("Okay, Accepting Client connection now");
Console.WriteLine(" ");
Console.WriteLine("Accepted new client connection.....");
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
string s = string.Empty;
while (!(s = reader.ReadLine()).Equals("Exit") || (s == null)) {
Console.WriteLine("From client -> " + s);
writer.WriteLine("From server -> " + s);
writer.Flush();
}
reader.Close();
writer.Close();
client.Close();
}
} catch (Exception e)
{
Console.WriteLine(e);
} finally
{
if (listener != null)
{
listener.Stop();
}
}
}
}
Now, the data I am trying to get are the heart rates and it changes every two seconds. However on TCP server I only get the first recorded value of a heart rate and it keeps repeating instead of getting new one.
There is a similar post I saw here on stackoverflow : UWP TCP receive data continuously
and someone suggested to use while loop which I did as you can see in the code.
Are there any other suggestions on what should I do?
Thanks
while (true)
{
await streamWriter.WriteLineAsync(data);
await streamWriter.FlushAsync();
}
The while(true) will keep repeating, meaning that it will always send 'data' at its current value. This is what causes your issue.
In my opinion, you should keep a connection to your TCP server open outside of your 'TrySend' method, and use this method only to send the data. This way you won't need to use this loop.
EDIT :
Try this :
private async void CharacteristicReadButton_Click()
{
while(true)
{
// BT_Code: Read the actual value from the device by using Uncached.
GattReadResult result = await selectedCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);
if (result.Status == GattCommunicationStatus.Success)
{
string formattedResult = FormatValueByPresentation(result.Value, presentationFormat);
rootPage.NotifyUser($"Read result: {formattedResult}", NotifyType.StatusMessage);
//string formattedResult = FormatValueByPresentation(result.Value, presentationFormat);
//rootPage.NotifyUser($"Read result: {formattedResult}", NotifyType.StatusMessage);
}
else
{
rootPage.NotifyUser($"Read failed: {result.Status}", NotifyType.ErrorMessage);
}
}
}
I am trying to get all messages id from my email,but it doesn't work. I get this answer:
$ BAD [CLIENTBUG] Unrecognised command\r\n\0\0\0\0.
How do I get the correct response?
string uids1 = ReceiveResponse("$ SELECT INBOX\r\n");
string uids = ReceiveResponse("$ UID SEARCH ALL" + "\r\n");//query to server
private string ReceiveResponse(string command)
{
_sb = new StringBuilder();
try
{
if (command != "")
{
if (_tcpClient.Connected)
{
_dummy = Encoding.ASCII.GetBytes(command);
_ssl.Write(_dummy, 0, _dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
_ssl.Flush();
_buffer = new byte[2048];
_tcpClient.ReceiveTimeout = 20000;
Encoding iso = Encoding.GetEncoding("ISO-8859-1");
do
{
try
{
bytes = _ssl.Read(_buffer, 0, 2048);
var msg = Encoding.UTF8.GetString(_buffer);
_sb.Append(msg);
Thread.Sleep(3);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} while (_tcpClient.Available > 0);
string text = _sb.ToString().Replace("\0", string.Empty);
return _sb.ToString();
}
catch (Exception ex)//if we have some problem show message
{
throw new ApplicationException(ex.Message);
}
}
Here is how my Client connects to the server:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Net.Sockets;
using System.IO;
using System;
using System.Text.RegularExpressions;
using UnityEngine.SceneManagement;
using Newtonsoft.Json;
using System.Linq;
public class ClientWorldServer : MonoBehaviour {
public bool socketReady;
public static TcpClient socket;
public static NetworkStream stream;
public static StreamWriter writer;
public static StreamReader reader;
public void ConnectToWorldServer()
{
if (socketReady)
{
return;
}
//Default host and port values;
string host = "127.0.0.1";
int port = 8080;
try
{
socket = new TcpClient(host, port);
stream = socket.GetStream();
writer = new StreamWriter(stream);
reader = new StreamReader(stream);
socketReady = true;
}
catch (Exception e)
{
Debug.Log("Socket error : " + e.Message);
}
}
}
Here is how i send data to the server using my Send function:
public void Send(string header, Dictionary<string, string> data)
{
if (stream.CanRead)
{
socketReady = true;
}
if (!socketReady)
{
return;
}
JsonData SendData = new JsonData();
SendData.header = "1x" + header;
foreach (var item in data)
{
SendData.data.Add(item.Key.ToString(), item.Value.ToString());
}
SendData.connectionId = connectionId;
string json = JsonConvert.SerializeObject(SendData);
var howManyBytes = json.Length * sizeof(Char);
writer.WriteLine(json);
writer.Flush();
Debug.Log("Client World:" + json);
}
As you can see i'm sending the data to the Stream like a string not like a byte array. As far as i know i should send the data as byte array prepending the size of the message and following the message. On the server side i have no clue how i can read that data.
Here is how i read it now(it works for now, but it will not work if i try to send more messages at once):
class WorldServer
{
public List<ServerClient> clients = new List<ServerClient>();
public List<ServerClient> disconnectList;
public List<CharactersOnline> charactersOnline = new List<CharactersOnline>();
public int port = 8080;
private TcpListener server;
private bool serverStarted;
private int connectionIncrementor;
private string mysqlConnectionString = #"server=xxx;userid=xxx;password=xxx;database=xx";
private MySqlConnection mysqlConn = null;
private MySqlDataReader mysqlReader;
static void Main(string[] args)
{
WorldServer serverInstance = new WorldServer();
Console.WriteLine("Starting World Server...");
try
{
serverInstance.mysqlConn = new MySqlConnection(serverInstance.mysqlConnectionString);
serverInstance.mysqlConn.Open();
Console.WriteLine("Connected to MySQL version: " + serverInstance.mysqlConn.ServerVersion + "\n");
}
catch (Exception e)
{
Console.WriteLine("MySQL Error: " + e.ToString());
}
finally
{
if (serverInstance.mysqlConn != null)
{
serverInstance.mysqlConn.Close();
}
}
serverInstance.clients = new List<ServerClient>();
serverInstance.disconnectList = new List<ServerClient>();
try
{
serverInstance.server = new TcpListener(IPAddress.Any, serverInstance.port);
serverInstance.server.Start();
serverInstance.StartListening();
serverInstance.serverStarted = true;
Console.WriteLine("Server has been started on port: " + serverInstance.port);
}
catch (Exception e)
{
Console.WriteLine("Socket error: " + e.Message);
}
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
/* run your code here */
while (true)
{
string input = Console.ReadLine();
string[] commands = input.Split(':');
if (commands[0] == "show online players")
{
Console.WriteLine("Showing connections\n");
foreach (CharactersOnline c in serverInstance.charactersOnline)
{
Console.WriteLine("Character name: " + c.characterName + "Character ID: " + c.characterId + "Connection id: " + c.connectionId + "\n");
}
}
continue;
}
}).Start();
while (true)
{
serverInstance.Update();
}
}
private void Update()
{
//Console.WriteLine("Call");
if (!serverStarted)
{
return;
}
foreach (ServerClient c in clients.ToList())
{
// Is the client still connected?
if (!IsConnected(c.tcp))
{
c.tcp.Close();
disconnectList.Add(c);
Console.WriteLine(c.connectionId + " has disconnected.");
CharacterLogout(c.connectionId);
continue;
//Console.WriteLine("Check for connection?\n");
}
else
{
// Check for message from Client.
NetworkStream s = c.tcp.GetStream();
if (s.DataAvailable)
{
StreamReader reader = new StreamReader(s, true);
string data = reader.ReadLine();
if (data != null)
{
OnIncomingData(c, data);
}
}
//continue;
}
}
for (int i = 0; i < disconnectList.Count - 1; i++)
{
clients.Remove(disconnectList[i]);
disconnectList.RemoveAt(i);
}
}
private void OnIncomingData(ServerClient c, string data)
{
Console.WriteLine(data);
dynamic json = JsonConvert.DeserializeObject(data);
string header = json.header;
//Console.WriteLine("Conn ID:" + json.connectionId);
string connId = json.connectionId;
int.TryParse(connId, out int connectionId);
string prefix = header.Substring(0, 2);
if (prefix != "1x")
{
Console.WriteLine("Unknown packet: " + data + "\n");
}
else
{
string HeaderPacket = header.Substring(2);
switch (HeaderPacket)
{
default:
Console.WriteLine("Unknown packet: " + data + "\n");
break;
case "004":
int accountId = json.data["accountId"];
SelectAccountCharacters(accountId, connectionId);
break;
case "005":
int characterId = json.data["characterId"];
getCharacterDetails(characterId, connectionId);
break;
case "006":
int charId = json.data["characterId"];
SendDataForSpawningOnlinePlayers(charId, connectionId);
break;
case "008":
Dictionary<string, string> dictObj = json.data.ToObject<Dictionary<string, string>>();
UpdateCharacterPosition(dictObj, connectionId);
break;
}
}
private bool IsConnected(TcpClient c)
{
try
{
if (c != null && c.Client != null && c.Client.Connected)
{
if (c.Client.Poll(0, SelectMode.SelectRead))
{
return !(c.Client.Receive(new byte[1], SocketFlags.Peek) == 0);
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void StartListening()
{
server.BeginAcceptTcpClient(OnConnection, server);
}
private void OnConnection(IAsyncResult ar)
{
connectionIncrementor++;
TcpListener listener = (TcpListener)ar.AsyncState;
clients.Add(new ServerClient(listener.EndAcceptTcpClient(ar)));
clients[clients.Count - 1].connectionId = connectionIncrementor;
StartListening();
//Send a message to everyone, say someone has connected!
Dictionary<string, string> SendDataBroadcast = new Dictionary<string, string>();
SendDataBroadcast.Add("connectionId", clients[clients.Count - 1].connectionId.ToString());
Broadcast("001", SendDataBroadcast, clients, clients[clients.Count - 1].connectionId);
Console.WriteLine(clients[clients.Count - 1].connectionId + " has connected.");
}
And this is how the server send back data to the client:
private void Send(string header, Dictionary<string, string> data, int cnnId)
{
foreach (ServerClient c in clients.ToList())
{
if (c.connectionId == cnnId)
{
try
{
//Console.WriteLine("Sending...");
StreamWriter writer = new StreamWriter(c.tcp.GetStream());
if (header == null)
{
header = "000";
}
JsonData SendData = new JsonData();
SendData.header = "0x" + header;
foreach (var item in data)
{
SendData.data.Add(item.Key.ToString(), item.Value.ToString());
}
SendData.connectionId = cnnId;
string JSonData = JsonConvert.SerializeObject(SendData);
writer.WriteLine(JSonData);
writer.Flush();
//Console.WriteLine("Trying to send data to connection id: " + cnnId + " data:" + sendData);
}
catch (Exception e)
{
Console.WriteLine("Write error : " + e.Message + " to client " + c.connectionId);
}
}
}
}
Here is my ServerClient class:
public class ServerClient
{
public TcpClient tcp;
public int accountId;
public int connectionId;
public ServerClient(TcpClient clientSocket)
{
tcp = clientSocket;
}
}
Can you please show me how i should modify my Send function on the client to send the data as byte array so i can create "TCP Message Framing" and how should i change my the following part on the server:
foreach (ServerClient c in clients.ToList())
{
// Is the client still connected?
if (!IsConnected(c.tcp))
{
c.tcp.Close();
disconnectList.Add(c);
Console.WriteLine(c.connectionId + " has disconnected.");
CharacterLogout(c.connectionId);
continue;
//Console.WriteLine("Check for connection?\n");
}
else
{
// Check for message from Client.
NetworkStream s = c.tcp.GetStream();
if (s.DataAvailable)
{
StreamReader reader = new StreamReader(s, true);
string data = reader.ReadLine();
if (data != null)
{
OnIncomingData(c, data);
}
}
//continue;
}
}
which is responsible for receving data on the server ?
Is it possible to change only these parts from the Client and on the Server and make it continue to work but this time properly with TCP Message Framing ?
Of course the listener on the client and the Send function of the server i'll remake once i understand how this framing should look like.
Your frames are already defined by cr/lf - so that much already exists; what you need to do is to keep a back buffer per stream - something like a MemoryStream might be sufficient, depending on how big you need to scale; then essentially what you're looking to do is something like:
while (s.DataAvailable)
{
// try to read a chunk of data from the inbound stream
int bytesRead = s.Read(someBuffer, 0, someBuffer.Length);
if(bytesRead > 0) {
// append to our per-socket back-buffer
perSocketStream.Position = perSocketStream.Length;
perSocketStream.Write(someBuffer, 0, bytesRead);
int frameSize; // detect any complete frame(s)
while((frameSize = DetectFirstCRLF(perSocketStream)) >= 0) {
// decode it as text
var backBuffer = perSocketStream.GetBuffer();
string message = encoding.GetString(
backBuffer, 0, frameSize);
// remove the frame from the start by copying down and resizing
Buffer.BlockCopy(backBuffer, frameSize, backBuffer, 0,
(int)(backBuffer.Length - frameSize));
perSocketStream.SetLength(backBuffer.Length - frameSize);
// process it
ProcessMessage(message);
}
}
}
I am trying to build a UCMA standalone outbound dialer. Unfortunately I can't find much information on how to connect to a SIP or how to configure this to begin with. I got a GetOnSIP and would like to associate it with my application. Any help would be appreciated!
Thanks
//set up my application
internal void Start()
{
_applicationId = ConfigurationManager.AppSettings["applicationId"];
_recipientSipUri = ConfigurationManager.AppSettings["recipientSipUri"];
//string urisToDialString = ConfigurationManager.AppSettings["numbersToDial"];
_urisToDial.Add("phone number goes here");
ServerPlatformSettings platformSettingsObj = new ServerPlatformSettings(_applicationId, Dns.GetHostEntry("localhost").HostName,
5060, string.Empty /* empty string for the GRUU */);
Utils.WriteDebug("Endpoint: " + platformSettingsObj.Localhost);
_platform = new CollaborationPlatform(platformSettingsObj);
_platform.AllowedAuthenticationProtocol = SipAuthenticationProtocols.None;
try
{
_platform.BeginStartup(ar =>
{
try
{
_platform.EndStartup(ar);
Console.WriteLine("Platform started.");
StartEndpoint();
Console.WriteLine("Platform Endpoint Initiated.");
CallSession sessionObj = new CallSession(_urisToDial.First(), _endpoint);
sessionObj.InitiateCall();
}
catch (RealTimeException ex)
{
Console.WriteLine(ex);
}
}, null);
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex);
}
}
private void StartEndpoint()
{
// Create a placeholder URI for the endpoint.
ApplicationEndpointSettings endpointSettings =
new ApplicationEndpointSettings("sip:default#" +
Dns.GetHostEntry("localhost").HostName);
// Make this a default routing endpoint, so that
// all requests sent to the listening port on this IP,
// regardless of To URI, will come to the endpoint.
endpointSettings.IsDefaultRoutingEndpoint = true;
// Create a new endpoint and register for AV calls.
_endpoint = new ApplicationEndpoint(_platform, endpointSettings);
_endpoint.RegisterForIncomingCall<AudioVideoCall>(OnCallReceived);
try
{
_endpoint.BeginEstablish(ar =>
{
try
{
_endpoint.EndEstablish(ar);
Console.WriteLine("Endpoint started.");
}
catch (RealTimeException ex)
{
Console.WriteLine(ex);
}
}, null);
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex);
}
}
public CallSession(string number, ApplicationEndpoint endpointObj)
{
// Set the host and port to which the INVITE should be sent
// i'm going to guess that this is where the sbc ip goes
ConnectionContext connectionContextObj = new ConnectionContext("192.168.0.56", 5060);
optionsObj.ConnectionContext = connectionContextObj;
//configure this to use udp
_phoneNumber = number;
_endpoint = endpointObj;
}
public bool InitiateCall()
{
bool isInitiated = true;
try
{
Utils.WriteDebug("About to Initiate a phone Call");
Conversation convObj = new Conversation(_endpoint);
AudioVideoCall avcallObj = new AudioVideoCall(convObj);
// Establish the call using the options we created
//avcall.BeginEstablish("sip:test#test.greenl.ee", optionsObj,
avcallObj.BeginEstablish("tel:+" + _phoneNumber, optionsObj,
ar =>
{
try
{
avcallObj.EndEstablish(ar);
Console.WriteLine("The call with Local Participant: " + avcallObj.Conversation.LocalParticipant + " and Remote Participant: " + avcallObj.RemoteEndpoint.Participant + " is now in the established state.");
}
catch (RealTimeException ex)
{
isInitiated = false;
Utils.LogError(ex);
}
},
null);
}
catch (InvalidOperationException ex)
{
isInitiated = false;
Utils.LogError(ex);
}
return isInitiated;
}