I need a socket communication between my own written java server and C# client, the problem is that the C# client can't receive any messages from my java server, but sending messages to my java server works.
my workflow:
Java: Create Server
Java: Waiting for Client connection
c#: Create Client
c#: Build connection to the server
c#: send a msg to the server
Java: msg received
java: send msg to c# client
c#: receiving msg from server <- this is the point where the client waits for a message but never get.
Java Server code:
public class Communicator {
private int m_port;
private Socket m_socket;
private ServerSocket m_serverSocket;
public Communicator(int port) {
this.m_port = port;
initConnection();
}
private void initConnection() {
try {
System.out.println("Creating Server");
m_serverSocket = new ServerSocket(m_port);
System.out.println("Waiting for client connection");
m_socket = m_serverSocket.accept();
System.out.println("Connection made");
} catch (IOException e) {
e.printStackTrace();
}
}
public String sendMsg(JSONMessage msg) {
try {
//get msg
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(m_socket.getInputStream()));
System.out.println("Waiting for msg...");
String answer = bufferedReader.readLine();
System.out.println("Received: " + answer);
//send msg
PrintWriter writer = new PrintWriter(m_socket.getOutputStream(),true);
writer.print(msg.getMsg());
System.out.println("Sending: " + msg.getMsg());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
My C# client code:
class Communicator
{
private int m_port;
private Thread mainThread;
public Communicator(int port)
{
m_port = port;
mainThread = new Thread(new ThreadStart(this.initConnection));
mainThread.Start();
}
public void initConnection()
{
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), m_port);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
Console.WriteLine("Trying to build connection");
server.Connect(ip);
Console.WriteLine("Connection successful");
NetworkStream ns = new NetworkStream(server);
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);
string data;
string welcome = "Hello";
Console.WriteLine("Sending: " + welcome);
sw.WriteLine(welcome);
sw.Flush();
Console.WriteLine("Receiving...");
data = sr.ReadLine();
// --> NEVER REACHING THIS POINT <---
Console.WriteLine("Received: " + data);
}
catch (SocketException e)
{
Console.WriteLine("Connection failed.");
return;
}
}
}
Does somebody has any idea why it never reaches my client code Console.WriteLine("Received: " + data); ?
I already tried with waits on both sides. I'm not getting any exceptions or error so I don't have really an idea where my problem is.
Thanks
If your receiver is expecting lines, your sender has to send lines. Your sender does not send lines, so the receiver waits forever until it gets one.
To avoid these kinds of problems in the future, you should always make a specification document that explains how your protocol works, ideally at the byte level. It should specify whether the protocol contains messages and if so, how the sender marks message boundaries and how the receiver identifies them.
Here, your receiver identifies message boundaries by looking for line endings. But your sender doesn't mark message boundaries with line endings. So the receiver waits forever.
If you had a protocol specification, this would have been obvious. In the future, I strongly urge you to invest the time to specify every protocol you implement.
You need to use println() which adds a new line instead of print(). In Java, readLine waits for a new line and I would expect it to do the same in C#. Also println will auto-flush, so you don't need to flush as well.
If you intend to use this connection mreo than once, you need to keep the BufferedReader and PrintWriter for the connection. (So I suggest you create these after the socket is created/accepted) Creating these multiple times for the same socket can be error prone and confusing.
Related
I've been watching the following pair of videos on how to create a TCP/IP connection : Server and Client
What I need to do is create a game (flipcard) in which I send only 2 coordinates for a matrix. Nothing more. Or less.
(the code will follow)
From what I've observed, he closes and reopens the connection, everytime he send a message. It's working. But what do I modify in the code to keep the connection open and detect when a message arrived ?
All my google-searches brought me to these 2 methods:
I have had luck using the socket object directly (rather than the TCP client). (But I do not want to use sockets)
Also uses sockets
When I click to start the server
private void bStartServer_Click(object sender, EventArgs e)
{
Thread tcpServerRunThread = new Thread(new ThreadStart(TCPServerRun));
tcpServerRunThread.Start();
}
Server Runs and waits for a connection
private void TCPServerRun()
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 2016);
tcpListener.Start();
updateUI("Listening");
while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();
updateUI("Connected");
Thread tcpHandlerThread = new Thread(new ParameterizedThreadStart(tcpHandler));
tcpHandlerThread.Start(client);
}
}
I handle my message
private void tcpHandler(object client)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 5004);
TcpClient mClient = (TcpClient)client;
NetworkStream stream = mClient.GetStream();
byte[] message = new byte[1024];
stream.Read(message,0, message.Length);
updateUI("New message = " + Encoding.ASCII.GetString(message));
stream.Close();
mClient.Close();
}
NOTE: updateUI is a function made by him to update a listbox item
Client side - almost like the server side
`private void button1_Click(object sender, EventArgs e)
{
Thread mThread = new Thread(new ThreadStart(ConnectAsClient));
mThread.Start();
}
private void ConnectAsClient()
{
// aici putem inlocui cu adresa de IP dorita
//client.Connect(IPAddress.Parse(textBox.Text), 5004);
client = new TcpClient();
//client.Connect(IPAddress.Parse("127.0.0.1"), 2016); // for when I'm not connected to network
client.Connect(IPAddress.Parse("my_ip_here"), 2016); // for when I am connected to the network
updateUI("connected");
NetworkStream stream = client.GetStream();
string s = "Hello world!";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
this.updateUI("Message sent!");
stream.Close();
// client.Close();
}`
If I'm not wrong, everytime he connects again, he creates a new connection, and not open the old one, right?
(It's my first time using TCP/IP, learning on my own, so I'd rather not use sockets, if possible)
-----------------------------------------------------------------------
Full link to my code (slighty modified from the videos provided at the beginning):
TCPClient
TCPServer
You are reconnecting every time you send the message. Use two different methods for this; one for connecting to the server and then another one for actually sending the message. Like so:
TcpClient client;
private void ConnectAsClient()
{
//client.Connect(IPAddress.Parse(textBox.Text), 5004);
client = new TcpClient();
//client.Connect(IPAddress.Parse("127.0.0.1"), 2016);
client.Connect(IPAddress.Parse("my_ip_here"), 2016);
updateUI("connected");
}
void SendMessage()
{
NetworkStream stream = client.GetStream();
string s = "Hello world!";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
this.updateUI("Message sent!");
}
i'm trying to make an application which allows the connection between 2 PCs(i planned on making it multi threaded later but lets keep it more simple at the beginning). This could be either used for chatting or sending data to the other pc and he does something to the data and sends it back.
This is my coding so far:
Server:
class Program
{
private static StreamWriter serverStreamWriter;
private static StreamReader serverStreamReader;
private static bool StartServer()
{
//setting up Listener
TcpListener tcpServerListener = new TcpListener(IPAddress.Any, 56765);
tcpServerListener.Start();
Console.WriteLine("Server Started!");
Console.WriteLine("Waiting for Connection...");
Socket serverSocket = tcpServerListener.AcceptSocket();
try
{
if (serverSocket.Connected)
{
Console.WriteLine("Client connected to Server!");
//open network stream on accepted socket
NetworkStream serverSockStream = new NetworkStream(serverSocket);
serverStreamWriter = new StreamWriter(serverSockStream);
serverStreamReader = new StreamReader(serverSockStream);
}
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return false;
}
return true;
}
static bool once = false;
static void Main(string[] args)
{
//Set Console Window Stuff
Console.Title = "Server";
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Green;
Console.BufferWidth = 120;
Console.Clear();
//Start Server
if (!StartServer())
Console.WriteLine("Error while Starting Server!");
//Waiting till Client sends Something
while (true)
{
string data = "Append Something to Me - ";
if (!once)//that check -.-
{
serverStreamWriter.WriteLine(data);
serverStreamWriter.Flush();
once = true;
}
Console.WriteLine("Client: " + serverStreamReader.ReadLine());
if (serverStreamReader.ReadLine() != data)
{
serverStreamWriter.WriteLine(data);
serverStreamWriter.Flush();
}
}
}
}
Client:
class Program
{
private static StreamReader clientStreamReader;
private static StreamWriter clientStreamWriter;
private static bool ConnectToServer()
{
try
{
TcpClient tcpClient = new TcpClient("127.0.0.1", 56765);
Console.WriteLine("Connected to Server!");
NetworkStream clientSockStream = tcpClient.GetStream();
clientStreamReader = new StreamReader(clientSockStream);
clientStreamWriter = new StreamWriter(clientSockStream);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return false;
}
return true;
}
private static void SendToServer(string message)
{
try
{
clientStreamWriter.WriteLine(message);
clientStreamWriter.Flush();
}
catch (Exception se)
{
Console.WriteLine(se.StackTrace);
}
}
static void Main(string[] args)
{
//Set Console Window Stuff
Console.Title = "Client";
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Red;
Console.BufferWidth = 120;
Console.Clear();
if (!ConnectToServer())
Console.WriteLine("Error while Connecting to Server!");
SendToServer("Send Me Data...");
//Waiting till Server sends Something
while (true)
{
string response = clientStreamReader.ReadLine();
Console.WriteLine(response + "|| Appending Text...");
response += "Appended Text!";
Console.WriteLine("Sended " + response + " back to server!");
SendToServer(response);
}
}
}
Even though this isn't really good coding, it works for me, BUT the main problem with this is it only works on my local machine. How would i make it so if i run the server app on my pc and my friend runs the client app on his pc those two connect!? Help would be really great since i wasn't able to found a detailed tutorial or such and i only created this Account to ask for help here :)
TcpClient tcpClient = new TcpClient("localhost", 3333);
Instead of "localhost", use the remote machine's address here.
Edit:
You don't seem to understand how this connection process works, so I'll try to explain it a little better.
Your server is opening up a socket on port 3333, listening for any connections. This process does not need any external IP adress.
You clients are trying to connect to the server. They need to know what server they're connecting to, so you need to supply them with an IP address. An example would be something like
TcpClient tcpClient = new TcpClient("127.0.0.1", 3333);
//this is identical to using "localhost"
There's no way for you to get around at some point using a remote address in the connection protocol. You can't just tell the client "connect on port 3333" and expect it to know exactly where it needs to connect.
The comment explaining how to resolve a local IP address isn't useful in your case, because what you ended up doing was just telling the client to connect to itself, as you resolved the client's IP address and tried to connect to that.
However, you can have multiple clients connect to the same server. In this case you won't need multiple remote IP addresses, you just tell all the clients to connect to the same remote address and then handle that on the server. This is where the RemoteEndPoint comes into effect.
At the server level you can use the RemoteEndPoint to find the IP address of the clients connecting to it, and use this IP address to return information to those clients.
All in all, you WILL have to use some hardcoded address for your initial
TcpClient tcpClient = new TcpClient(address, 3333);
step. There's no way around this.
I'm new to C# UDP coding and I have some 'strange' behaviour when using an UDP client locally on my pc.
I want to send UDP data from one port (11000) on my pc to another port (12000) on the same pc.
This is a snippet from my code :
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}
If I run this, I get an exception :
Sending...
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP)
at System.Net.Sockets.UdpClient.Receive(IPEndPoint& remoteEP)
at test.MyClass.Execute() in C:\Temp\test\Class1.cs:line 40
The exception seems to occur on this line :
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
At the moment of the SendData(), the Receive is throwing the exception. When not doing the send, I don't get the exception. It looks like the send is causing the receive to return with an exception.
When I use the real ip address of my pc, I have the same behaviour. However, when I use any other ip address, even if it's unassigned to any pc (e.g. 192.168.10.10), it's working well : it sends the string and the Receive() keeps waiting for incoming data.
The error happens because there is no socket open on the port to which you are sending.
For the purposes of simply testing UDP communications, you can fix your code example simply by changing the port to which you are sending. I.e. change the Connect() method call to this:
udpClient.Connect(IPAddress.Parse(IPADDR), 11000);
This will cause the socket to send to itself. Your code will work successfully with just this change.
For the record, here is about the simplest possible demonstration code that uses UdpClient:
UdpClient client = new UdpClient(0, AddressFamily.InterNetwork);
byte[] datagram = Encoding.ASCII.GetBytes("hello world!");
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)client.Client.LocalEndPoint).Port);
client.Send(datagram, datagram.Length, ipEndPoint);
datagram = client.Receive(ref ipEndPoint);
Console.WriteLine("Received: \"" + Encoding.ASCII.GetString(datagram) + "\"");
Of course, in a real network I/O situation, you will have two endpoints, each bound to its own local port, sending to the other endpoint's port. So neither your code example, nor this simpler one I present is very useful as an actual working program. But it does allow you to learn some things about how the socket API works.
You are trying to send from one socket (UdpClient which is socket wrapper) to itself. Thats not how the things work in UDP (nor in other IP protocols). You need 2 sockets. One for sending one for receiving. Connect method is poorly named since UDP protocol is conectionless but thats not your fault.
Other than that you need to put socket in listening state before sending to it. So you first need to start thread that listens and then send.
You need to better design your program but this will work:
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private UdpClient recipient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
recipient = new UdpClient(new IPEndPoint(IPAddress.Parse(IPADDR), 12000));
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Parse(IPADDR), 11000);
Byte[] receiveBytes = this.recipient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received: " + Encoding.ASCII.GetString(receiveBytes));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}
What is the best way to make a Tcpclient auto reconnect to the server when
it's disconnected (e.g. by the server itself)?
The code I'm currently using is:
public void ClientWork()
{
TcpClient client = new TcpClient();
try
{
try
{
client.Connect(ip, port);
}
catch(Exception ex)
{
logger.ErrorFormat("client.Connect: {0}", ex.Message);
return false;
}
NetworkStream ns = client.GetStream();
byte[] buff;
while (__bRunning)
{
buff = new byte[1000];
ns.Read(buff, 0, 1000);
string line = System.Text.Encoding.Default.GetString(buff);
}
//ns.Close();
client.Close();
}
catch(Exception e)
{
//Reconnect?
client.Close();
client = null;
return false;
}
}
I'm using C# .NET
There is no events available to get notification for broken connection.
There could be 2 possible solution.
Polling. You have separate thread that try to poll socket continually done in different thread. Refer Instantly detect client disconnection from server socket
If you have low level control over socket or the interface which is using socket, you can do try..catch for read and write methods or try..catch for wrappers of read and write methods and when there is any exception you can re-connect and try to read and write.
I am creating a socket server in C# and a client in PHP. The conversation between client and server is something like this:
client connects
server sends welcome message
client sends data
server sends response
(repeat step 3 - 4 until client disconnects)
It works until step 3. The data from the client is received by the server. However, the client waits forever until the server sends its response and eventually times out.
Here is the relevant C# code:
class Program
{
private const int CONNECT_QUEUE_LENGTH = 4;
static void ListenForRequests()
{
Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSock.Bind(new IPEndPoint(IPAddress.Any, 9999));
listenSock.Listen(CONNECT_QUEUE_LENGTH);
listenSock.Blocking = true;
byte[] data = new byte[1024];
while (true)
{
Socket newConnection = listenSock.Accept();
newConnection.Blocking = true;
// Create new thread for each request
var t = new Thread(() => new RequestHandler(newConnection));
t.Start();
}
}
}
class RequestHandler
{
public RequestHandler(Socket socket)
{
Util.WriteToSocket("A message", socket);
Console.WriteLine("Received: " + Util.ReadSocketToEnd(socket).Length);
Util.WriteToSocket("Fin!", socket);
}
}
static class Util
{
public static string ReadSocketToEnd(Socket newConnection)
{
var sb = new StringBuilder();
byte[] data = new byte[1024];
int receivedDataLength = newConnection.Receive(data);
while (receivedDataLength > 0)
{
try
{
sb.Append(Encoding.UTF8.GetString(data, 0, receivedDataLength));
receivedDataLength = newConnection.Receive(data);
}
catch (SocketException)
{
break;
}
}
return sb.ToString();
}
public static void WriteToSocket(string message, Socket client)
{
byte[] data = Encoding.UTF8.GetBytes(message);
client.Send(data, SocketFlags.None);
}
}
And here is the simple PHP client, without any error handling etc:
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, '127.0.0.1', 9999);
print 'receiving: ' . chr(10);
print socket_read ($socket, 10) . chr(10);
print 'receive end' . chr(10);
$message = str_repeat("Message to sent", 1000);
socket_write($socket, $message, strlen($message));
print 'message sent' . chr(10);
print 'reading fin' . chr(10); // This is printed, but a response is never received
print socket_read ($socket, 10) . chr(10);
print 'fin read!' . chr(10);
socket_shutdown($socket);
You're reading from the socket until all the data has been read - meaning "all the data until the socket is closed". Your PHP client is writing data, but not closing the socket - so the server is waiting forever.
TCP sockets provide a stream of data. There's no concept of "the end of the current message" which is what it looks like you want.
The three ways of handling this are usually:
A message delimiter (e.g. a line break)
A message length prefix (number of bytes in the message just before the message itself)
Use a different connection for each request/response pair
You could potentially use a read with a timeout, and assume that if you haven't seen any more data in the last 5 seconds, you've got the whole message - but that's fragile, inefficient and generally a bad idea.