Fleck WebSockets - c#

I want to use Fleck for my WebSocket project,
Server side looks pretty straightforward, but how to I differentiate opened connections. is there some sort of ID? The only way I can think of is to create GUID in OnOpen event and pass it back to client. is there a smarter solution?
Basic server set up:
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
Console.WriteLine(message);
allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
};
E.G. how would I make a chat room so all connection receive message except for the one sending.
Fleck server here: https://github.com/statianzo/Fleck

Fleck now creates a Guid Id on the WebSocketConnectionInfo for every connected client. This will help in cases where multiple connections are using the same IP. See the related commit here:
https://github.com/statianzo/Fleck/commit/fc037f49362bb41a2bc753a5ff51cc9da40ad824

Ask the user for a user name, and attach the username to the the socket address:
var wsimpl = window.WebSocket || window.mozWebSocket;
window.ws = new wsimpl('http://localhost:8080/myApp_' + userName, myProtocol);
then strip out the userName on the service side after the socket has been opened with socket.WebSocketConnectionInfo.path. There is also a clientip property that can be used also. I am doing this and it works great.

I started something similar to what you are asking I am doing. In my case I am using the ConnectionInfo.Path to differ between what my sockets are doing.
You can gain a lot of information already out of the ConnectionInfo
socket.ConnectionInfo.{Host|Path|Origin|SubProtocol|ClientIPAddress|Cookies}
So to answer your question to give it to everyone but the sender you can differentiate each socket based on the ConnectionInfo (if applicable you could create a UID out of this info also)
As a very basic example:
If you know each Client will have a different IP something like the following would work:
socket.OnMessage = message =>
{
foreach (IWebSocketConnection socketConnection in allSockets.Where(socketConnection => socket.ConnectionInfo.ClientIpAddress != socketConnection.ConnectionInfo.ClientIpAddress))
{
socketConnection.Send("Echo: " + message);
}
};

It's a different socket instance per client, so I would have thought you should be able to do:
allSockets.Where(x => x != socket).ToList().ForEach(s => s.Send("Echo: " + message));

Related

Accessing value used in LINQ Select within a foreach

Given a list of IP addresses:
List<string> ipList = new List<string>(); //example: 192.168.0.1, 192.168.0.2, 192.168.0.3 etc.
I am attempting to loop over each IP in the list, in a parallel fashion and then print a meaningful message to screen:
foreach (PingReply pingReply in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new Ping().Send(ip)))
{
Console.WriteLine($"Ping status: {pingReply.Status} for the target IP address: {ip}");
}
I am unable to access ip in that context. I would really like to understand how I could go about accessing each relative ip as I am sending them out?
I have explored the PingReply object but PingReply.Address as an example contains the host (sender) IP, so it cannot help with this requirement. I really wish the PingReply object contained the Ip that was pinged!
UPDATE
As per example provided by #haim770 and #MindSwipe I ended up using:
foreach (var pingResponseData in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => new { ip, pingReply = new Ping().Send(ip) }))
{
Console.WriteLine($"Ping status: {pingResponseData.pingReply.Status} for the target IP address: {pingResponseData.ip}");
}
UPDATE 2
As per comment from #pinkfloydx33 regarding use of ValueTuple I have done as per the following example:
foreach (var (ip, reply) in ipList.AsParallel().WithDegreeOfParallelism(ipList.Count).Select(ip => (ip, new Ping().Send(ip, 150))))
{
Console.WriteLine($"Ping status: {reply.Status} for the target IP address: {ip}");
}
You're currently only selecting the pingReply, not the ip and the pingReply, to do that you'll need to select a new anonymous type and iterate over that. Like so:
foreach (var (pingReply, ip) in ipList.AsParallel().WithDegreeOfParallelism(64).Select(ip => (ip, Ping().Send(ip))))
{
// Here 'i' is an object with the properties 'ip' and 'pingReply'
Console.WriteLine($"Ping status: {i.pingReply.Status} for the target IP address: {i.ip}");
}
Edit: Just noticed now that haim770 posted basically this in their comment
Edit 2: Thanks pinkfloydx33 for pointing out I could use tuple deconsturcting
Calling the synchronous Ping.Send in parallel with a degree of parallelism = 64 is quite inefficient, because as many as 64 threads are blocked during the parallel execution (provided that the ThreadPool has enough threads available to satisfy the demand, which is doubtful). A more efficient way to do the pinging is to use the asynchronous Ping.SendPingAsync method. To invoke this method in a way that no more than 64 asynchronous operations will be simultaneously in-flight, you will need a Parallel.ForEach equivalent that works with asynchronous delegates. Currently there is no such thing available built-in (it will probably be available in .NET 6), but you can find lots of custom implementations if you search for ForEachAsync. There is one here for example. Then you will be able to do this:
var ipList = new List<string>() {"192.168.0.1", "192.168.0.2", "192.168.0.3"}; // etc
ipList.ForEachAsync(async ip =>
{
var ping = new Ping();
var reply = await ping.SendPingAsync(ip);
Console.WriteLine($"IP '{ip}' ping reply status: {reply.Status}");
}, dop: 64).Wait();
You could also await the completion of the operation, instead of using the blocking Wait, provided that you are calling it from an async method.

How to check database connection in MongoDB [duplicate]

I use MongoDB drivers to connect to the database. When my form loads, I want to set up connection and to check whether it is ok or not. I do it like this:
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("reestr");
But I do not know how to check connection. I tried to overlap this code with try-catch, but to no avail. Even if I make an incorrect connectionString, I still can not get any error message.
To ping the server with the new 3.0 driver its:
var database = client.GetDatabase("YourDbHere");
database.RunCommandAsync((Command<BsonDocument>)"{ping:1}")
.Wait();
There's a ping method for that:
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
server.Ping();
full example for 2.4.3 - where "client.GetServer()" isn't available.
based on "Paul Keister" answer.
client = new MongoClient("mongodb://localhost");
database = client.GetDatabase(mongoDbStr);
bool isMongoLive = database.RunCommandAsync((Command<BsonDocument>)"{ping:1}").Wait(1000);
if(isMongoLive)
{
// connected
}
else
{
// couldn't connect
}
I've had the same question as the OP, and tried every and each solution I was able to find on Internet...
Well, none of them worked to my true satisfaction, so I've opted for a research to find a reliable and responsive way of checking if connection to a MongoDB Database Server is alive. And this without to block the application's synchronous execution for too long time period...
So here are my prerequisites:
Synchronous processing of the connection check
Short to very short time slice for the connection check
Reliability of the connection check
If possible, not throwing exceptions and not triggering timeouts
I've provided a fresh MongoDB Installation (version 3.6) on the default localhost URL: mongodb://localhost:27017. I've also written down another URL, where there was no MongoDB Database Server: mongodb://localhost:27071.
I'm also using the C# Driver 2.4.4 and do not use the legacy implementation (MongoDB.Driver.Legacy assembly).
So my expectations are, when I'm checking the connection to the first URL, it should give to me the Ok for a alive connection to an existing MongoDB server, when I'm checking the connection to the second URL it should give to me the Fail for a non-existing MongoDB server...
Using the IMongoDatabase.RunCommand method, queries the server and causes the server response timeout to elapse, thus not qualifying against the prerequisites. Furthermore after the timeout, it breaks with a TimeoutException, which requires additional exception handling.
This actual SO question and also this SO question have delivered the most of the start information I needed for my solution... So guys, many thanks for this!
Now my solution:
private static bool ProbeForMongoDbConnection(string connectionString, string dbName)
{
var probeTask =
Task.Run(() =>
{
var isAlive = false;
var client = new MongoDB.Driver.MongoClient(connectionString);
for (var k = 0; k < 6; k++)
{
client.GetDatabase(dbName);
var server = client.Cluster.Description.Servers.FirstOrDefault();
isAlive = (server != null &&
server.HeartbeatException == null &&
server.State == MongoDB.Driver.Core.Servers.ServerState.Connected);
if (isAlive)
{
break;
}
System.Threading.Thread.Sleep(300);
}
return isAlive;
});
probeTask.Wait();
return probeTask.Result;
}
The idea behind this is the MongoDB Server does not react (and seems to be non-existing) until a real attempt is made to access some resource on the server (for example a database). But retrieving some resource alone is not enough, as the server still has no updates to its state in the server's Cluster Description. This update comes first, when the resource is retrieved again. From this time point, the server has valid Cluster Description and valid data inside it...
Generally it seems to me, the MongoDB Server does not proactivelly propagate its Cluster Description to all connected clients. Rather then, each client receives the description, when a request to the server has been made. If some of you fellows have more information on this, please either confirm or deny my understandings on the topic...
Now when we target an invalid MongoDB Server URL, then the Cluster Description remains invalid and we can catch and deliver an usable signal for this case...
So the following statements (for the valid URL)
// The admin database should exist on each MongoDB 3.6 Installation, if not explicitly deleted!
var isAlive = ProbeForMongoDbConnection("mongodb://localhost:27017", "admin");
Console.WriteLine("Connection to mongodb://localhost:27017 was " + (isAlive ? "successful!" : "NOT successful!"));
will print out
Connection to mongodb://localhost:27017 was successful!
and the statements (for the invalid URL)
// The admin database should exist on each MongoDB 3.6 Installation, if not explicitly deleted!
isAlive = ProbeForMongoDbConnection("mongodb://localhost:27071", "admin");
Console.WriteLine("Connection to mongodb://localhost:27071 was " + (isAlive ? "successful!" : "NOT successful!"));
will print out
Connection to mongodb://localhost:27071 was NOT successful!
Here a simple extension method to ping mongodb server
public static class MongoDbExt
{
public static bool Ping(this IMongoDatabase db, int secondToWait = 1)
{
if (secondToWait <= 0)
throw new ArgumentOutOfRangeException("secondToWait", secondToWait, "Must be at least 1 second");
return db.RunCommandAsync((Command<MongoDB.Bson.BsonDocument>)"{ping:1}").Wait(secondToWait * 1000);
}
}
You can use it like so:
var client = new MongoClient("yourConnectionString");
var database = client.GetDatabase("yourDatabase");
if (!database.Ping())
throw new Exception("Could not connect to MongoDb");
This is a solution by using the try-catch approach,
var database = client.GetDatabase("YourDbHere");
bool isMongoConnected;
try
{
await database.RunCommandAsync((Command<BsonDocument>)"{ping:1}");
isMongoConnected = true;
}
catch(Exception)
{
isMongoConnected = false;
}
so when it fails to connect to the database, it will throw an exception and we can handle our bool flag there.
If you want to handle connection issues in your program you can use the ICluster.Description event.
When the MongoClient is created, it will continue to attempt connections in the background until it succeeds.
using MongoDB.Driver;
using MongoDB.Driver.Core.Clusters;
var mongoClient = new MongoClient("localhost")
mongoClient.Cluster.DescriptionChanged += Cluster_DescriptionChanged;
public void Cluster_DescriptionChanged(object sender, ClusterDescriptionChangedEventArgs e)
{
switch (e.NewClusterDescription.State)
{
case ClusterState.Disconnected:
break;
case ClusterState.Connected:
break;
}
}

How to properly listen for UDP packets while doing other things in Visual C#

Alright, so I'm pretty new to C# and I'm definitely pretty new to graphical programming. I'm using Visual Studio 2015 and writing my application in C#.
I have this hunk of code that I've been toying around with for a while. Essentially my program will send the HELLO, to the server, but the server isn't sending HELLO back. I have no firewall in the middle of client and server right now, but the process is getting hung waiting for the reply back. I honestly don't even want to do it this way, I want the listener to always run in the background while the user does other stuff so that my program functions, well normal. So I come to you oh great Stackoverflow... because I am definitely doing it wrong! Could someone please point me the right direction?
Current Code:
private void button1_Click(object sender, EventArgs e)
{
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(this.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
this.send_message("127.0.0.1", 10545, 10545, "HELLO");
this.send_message("127.0.0.1", 10545, 10545, "AUTH:" + this.login.Text + ":" + hash);
//ListenForData.Start();
}
private void send_message(string server, int localPort, int remotePort, string message)
{
label4.Text = "Listening on port:" + localPort;
IPEndPoint lep = new IPEndPoint(IPAddress.Any, localPort);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress loginServer = IPAddress.Parse(server.ToString());
byte[] sendbuf = Encoding.ASCII.GetBytes(message);
IPEndPoint ep = new IPEndPoint(loginServer, remotePort);
s.SendTo(sendbuf, ep);
try
{
UdpClient udpClient = new UdpClient(lep);
byte[] bytes = udpClient.Receive(ref lep);
label4.Text = ep.ToString();
} catch ( Exception ex )
{
Console.WriteLine(ex.ToString());
}
}
UDPATE:
private static void UDPListener(object obj)
{
Task.Run(async () =>
{
using (var udpClient = new UdpClient(10545))
{
string rMessage = "";
string[] rArgs = new string[0];
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
var receivedResults = await udpClient.ReceiveAsync();
rMessage += Encoding.ASCII.GetString(receivedResults.Buffer);
rArgs = rMessage.Split(new char[] { ':' });
if( rArgs[0] == "HELLO")
{
Console.Write("Received HELLO from server.");
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(obj.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
send_message("127.0.0.1", 10545, 10545, "AUTH:" + obj.login.Text + ":" + hash);
}
}
}
});
}
You can safely ignore the advice from Blindy. The UdpClient.ReceiveAsync() method is specifically designed around the Task paradigm, and is much more efficient than dedicating a thread to receiving data. Because the Task is awaitable, it's also easier to integrate the ReceiveAsync() approach with a GUI program (e.g. Winforms or WPF). That said, for all that to work, you want to execute the ReceiveAsync() call in the UI thread, rather than in another Task.
Unfortunately, lacking a good, minimal, complete code example that clearly illustrates your question, it's not possible to say for sure how that would look. But it most likely would involve making your UDPListener() method an async method and calling it from the UI thread. Also, since you say the method can't access non-static members, the obvious solution to that is to make the method itself non-static. E.g.:
private static async Task UDPListener(object obj)
{
using (var udpClient = new UdpClient(10545))
{
string rMessage = "";
string[] rArgs = new string[0];
while (true)
{
//IPEndPoint object will allow us to read datagrams sent from any source.
var receivedResults = await udpClient.ReceiveAsync();
rMessage += Encoding.ASCII.GetString(receivedResults.Buffer);
rArgs = rMessage.Split(new char[] { ':' });
if( rArgs[0] == "HELLO")
{
Console.Write("Received HELLO from server.");
byte[] data = new byte[512];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(Encoding.UTF8.GetBytes(obj.password.Text));
var hash = BitConverter.ToString(result).Replace("-", "");
send_message("127.0.0.1", 10545, 10545, "AUTH:" + obj.login.Text + ":" + hash);
}
}
}
}
It is not clear from your updated question whether you have fixed your failed to receive a reply yet. But if you have not changed your send_message() method, it has some obvious problems, especially in the context of creating a separate UdpClient instance to receive datagrams.
The most obvious issue is that you do not create the UdpClient instance which you're expecting to use to receive the response until after you have sent the message. This is wrong for two reasons:
It's entirely possible that the remote endpoint will send the response before you've created the socket. If that happens, the datagram will just be dropped.
More importantly, the usual design for a server is to send a response to the remote endpoint that sent it the message in the first place. I.e. in this case that would be the socket s. Even if you did create the udpClient object before calling s.SendTo(), the reply would actually be sent to the s socket, not the udpClient.Client socket.
Again, without a good code example it's not possible to know what your server actually does. But whether it behaves like a normal server, or is some non-standard implementation, the code you've posted cannot reliably receive a response from the server.
You should fix your design so that your client creates only a single socket (e.g. an initial UdpClient instance). You would prepare for communication by calling ReceiveAsync(), and only once you've done that, thus ensuring you're ready to receive a response, then you can send data.
Make sure that you create only this single object.
Note also that client-side implementations typically do not bind to a specific port. Instead, you let the OS assign a port. Only the server needs to bind to a specific port, so that inbound requests from unknown endpoints can know to what port to send their request. The server's receive operation will include the port number of the client, so the server will know to what port to send its response, without the client having selected any special port number.
Finally, I strongly recommend you study existing socket programming tutorials, and especially the Winsock Programmer's FAQ. None of the material there is directly applicable to the .NET socket API, but most of the issues you will have trouble with are exactly the kinds of things documented there. It is not possible to use the .NET socket API without also having a good basic comprehension of socket programming generally.
If the above does not get you headed in the right direction, please make sure that any future questions you ask include a good code example, as described in the link I provided above. Note that for any networking question, a complete code example includes both the client and server. It is not possible for anyone to fully understand your question, never mind to test and fix your code example, without implementations of both.

StreamInsight: Using a local Observer for a RemoteObservable

I've been playing with StreamInsight v2.3 and the newer Rx capabilities it provides. I'm investigating the use of SI for an Event Sourcing implementation. I've tweaked some of the MSDN sample code to get the following:
code for the server process:
using (var server = Server.Create("Default"))
{
var host = new ServiceHost(server.CreateManagementService());
host.AddServiceEndpoint(typeof(IManagementService), new WSHttpBinding(SecurityMode.Message), "http://localhost/SIDemo");
host.Open();
var myApp = server.CreateApplication("SIDemoApp");
var mySource = myApp.DefineObservable(() => Observable.Interval(TimeSpan.FromSeconds(1))).ToPointStreamable(x => PointEvent.CreateInsert(DateTimeOffset.Now, x), AdvanceTimeSettings.StrictlyIncreasingStartTime);
mySource.Deploy("demoSource");
Console.WriteLine("Hit enter to stop.");
Console.ReadLine();
host.Close();
}
code for the client process:
using (var server = Server.Connect(new System.ServiceModel.EndpointAddress(#"http://localhost/SIDemo")))
{
var myApp = server.Applications["SIDemoApp"];
var mySource = myApp.GetObservable<long>("demoSource");
using (var mySink = mySource.Subscribe(x => Console.WriteLine("Output - {0}", x)))
{
Console.WriteLine("Hit enter to stop.");
Console.ReadLine();
}
}
Trying to run this produces the following error:
Reading from a remote
'System.Reactive.Linq.IQbservable`1[System.Int64]' is not supported.
Use the 'Microsoft.ComplexEventProcessing.Linq.RemoteProvider.Bind'
method to read from the source using a remote observer.
The sample code I started with defines an observer and sink and binds it in the StreamInsight server. I'm trying to keep the observer in the client process. Is there a way to set up an observer in the client app for a remote StreamInsight source? Does this have to be done through something like a WCF endpoint in the server that is observed by the client?
Actualy error is directing to the solution. You need 'bind' to the source.
Please check the snippet below:
//Get SOURCE from server
var serverSource = myApp.GetStreamable<long>("demoSource");
//SINK for 'demoSource'
var sinkToBind = myApp.DefineObserver<long>( ()=> Observer.Create<long>( value => Console.WriteLine( "From client : " + value)));
//BINDING
var processForSink = serverSource.Bind(sinkToBind).Run("processForSink");
Also note that, sink will run on server, not like I guessed at first that it will run on client. If you look to console apps for both server and client, console output is writing to server app.
If even there is a way to run sink on client, I don't know and I like to know that too.

Socket programming- client server principles

I'm embarrassed to even ask this question, but after an exhausting search in google (starting to have MSDN...), I've decided to post it:
Just now started learning client-server programming (using C#), and trying to write my first code using tcpClient. I'm writing both the server side and the client side.
here's my question: Constantly, the client sends one String to the server, and then the server sends a String back to the client and so forth.
Can't the server send 2 Strings in a row? he has to wait for the client response? is this the principle of client-server??
Once again, sorry for the lousy question.
Thanks...
<>
I'll try to post some of my code (a long one...).
I tryed to cut the redandent parts, so hope the code makes any sense... (i marked the main problam with //*********)
public class MServer2
{
Dictionary<String, String> nameAndPass = new Dictionary<String, String>();
Dictionary<String, List<String> > nameAndMail = new Dictionary<String, List<String>>();
public static void Main()
{
new MServer2();
}
public MServer2()
{
TcpListener server = new TcpListener(8500);
try
{
server.Start();
Console.WriteLine("started " + server);
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("connection accepted " + client);
new Server1(client, nameAndPass, nameAndMail);
}
}
catch (Exception e)
{
Console.WriteLine("exception" + e);
}
finally
{
server.Stop();
}
}
class Server1
{
TcpClient client;
NetworkStream netStream;
Dictionary<String, String> nameAndPass1 = new Dictionary<String, String>();
Dictionary<String, List<String>> nameAndMail1 = new Dictionary<String, List<String>>();
internal Server1(TcpClient client, Dictionary<String, String> nameandPassFromFile, Dictionary<String, List<String> > nameAndMailsFromFile)
{
nameAndPass1 = nameandPassFromFile;
nameAndMail1 = nameAndMailsFromFile;
this.client = client;
Thread thr = new Thread(new ThreadStart(Run));
thr.Start();
}
public void Run()
{
try
{
netStream = client.GetStream();
StreamReader reader = new StreamReader(netStream);
StreamWriter writer = new StreamWriter(netStream);
writer.AutoFlush = true;
Console.WriteLine("beginning to receive loop");
writer.WriteLine("Choose your user name.");
strFromClient = reader.ReadLine();
userName = strFromClient;
writer.WriteLine("Choose your user password.");
strFromClient = reader.ReadLine();
password = strFromClient;
writer.WriteLine("Do you want to see the list of email addresses? (y/n)");
strFromClient = reader.ReadLine();
//***********************************************************************************
//HERE'S MY PROBLAM:
//HERE THE CLIENT WILL GET A STRING SHOWING HIS EMAILS, AND I WANT HIM TO GET ANOTHER STRING ASKING "Do you want to add an email address? (y/n)", BUT IT LOOKS LIKE THE SERVER "WAITS" FOR A RESPONSE FROM THE CLIENT TO SHOW THE NEXT STRING...
if (strFromClient == "y")
{
String tmpStr = null;
List<String> tmp = nameAndMail1[userName];
for(int i=0; i<nameAndMail1[userName].Count; i++)
{
tmpStr += tmp[i] + " ";
}
writer.WriteLine(tmpStr);
}
writer.WriteLine("Do you want to add an email address? (y/n)");
strFromClient = reader.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
EDIT VOL 2
OK! After 2 hours of misery, I think I found the problam thanks to Phil Frost (the genius!) --- the problam is probably in the client... (Im souch an a-hole!).
The server does send 2 string in a row, but my stupid implementation of the client side doesn't show a message (which recived from the server) that doesn't follow a message sent by the client...
So once again I need your help. Here's a view of how I designed the client form:
My lack of experience led me to connect to the server when the "connect to server" button is pressed, and only when the "send Message" button is pressed, a message from the server is desplayed. The problam is when 2 (or more) messages from the server are recived without sending a message from the client to the server- the client doesn't know that a new message is recived!
Where do I suppose to recive the messages from the server? ('where' means under which function, for example- right now it happens in the sendMessage_click function).
thanks again for all the help so far!!
This question is neither lousy nor trivial. You are touching an important point in protocol design.
AFAIK, there are 2 ways to skin this particular cat:
"Dialog" (your way) ... Request is followed by reply, is followed by next request and so on. This has the big advantage of being easy, but the big disadvantage of only one command per connection being processed at any point in time
"Async" (Both parties can send without waiting for an answer) ... This has the implementation difficulty, that you need some sort of request-ID to make it possible to know, which reply belongs to which request: Imagine the client sending two requests, the first taking longer to process than the second: The replies would be in a different order than the requests.
The choice between these variants is not allways an easy one, but the trend goes towards the async model.
Additional difficulties in the async flavour include a mechanism to make sure, only one message is sent at a time (interweaving messages will most likely result in an unparseable stream) and timeout considerations.
Yes, the server can send two strings in a row. But probably not if your server is blocked on read(). Perhaps if you included some more details about your program, a more specific answer could be provided.
In TCP the client-to-server and server-to-client channels are two independent streams. Either party can send at any time.

Categories