i have a trouble with my socket programming code.
when i use below:
var ipaddress = IPAddress.Parse("192.168.1.100");
IPAddress add = new IPAddress(ipaddress.GetAddressBytes());
TcpListener tcpListener = null;
tcpListener = new TcpListener(add, 53);
tcpListener.Start();
Console.WriteLine("Waiting for a connection...");
while (true)
{
Thread.Sleep(10);
TcpClient tcpClient = tcpListener.AcceptTcpClient();
//Read the data stream from the client.
byte[] bytes = new byte[512];
NetworkStream stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
SocketHelper helper = new SocketHelper();
helper.processMsg(tcpClient, stream, bytes);
}
i receive this error:
Additional information: Only one usage of each socket address (protocol/network address/port) is normally permitted
but i changed my cod to below :
static Socket sktListener;
var ipaddress = IPAddress.Parse("192.168.1.100");
IPAddress add = new IPAddress(ipaddress.GetAddressBytes());
sktListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(add, 53);
sktListener.Connect(ipLocal);
if (sktListener.Connected)
{
byte[] bytes = new byte[512];
int i = sktListener.Receive(bytes);
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
but it dose not any work. and stop on this line
int i = sktListener.Receive(bytes);
IPAddress.Parse() returns a new IPAddress object, you do not need to create a second IPAddress object from the first object's bytes:
IPAddress add = IPAddress.Parse("192.168.1.100");
Regarding the usage error in the first code, it means 192.168.1.100:53 is already in use by another socket.
Your second code is not creating a server, it is creating a client that connects to a server. Assuming these codes are meant to work together, then it makes sense why Receive() is blocking - your client is expecting to receive data that your server is not sending. Your server code is expecting a new client to send data, but your client is not sending anything.
Related
I have a hardware that streams data to a windows server, and I have IP and port of this server. Now I want to connect unity app as a TCP client to this server. I have tried many solutions, but still have hard time to figure out best way to do this. Any help is highly appreciated. One issue that I have with current tutorials is that most of them define a unity server and try to connect another unity app as client and mostly based on localhost. However, I just want to connect a unity app as a TCP client to a server which I have IP and port.
Warm regards,
enter image description here
First of all, at the top of your script:
using System;
using System.Net.Sockets;
Then, create an instance of TcpClient and begin the connection:
socket = new TcpClient
{
// dataBufferSize is in bytes
ReceiveBufferSize = dataBufferSize,
SendBufferSize = dataBufferSize
};
socket.BeginConnect(ip, port, ConnectCallback, socket);
In ConnectCallback():
private void ConnectCallback(IAsyncResult asyncResult)
{
socket.EndConnect(asyncResult);
if (!socket.Connected) return;
// stream is a NetworkStream you should declare somewhere
stream = socket.GetStream();
// receiveBuffer is a byte[] you should declare somewhere
receiveBuffer = new byte[dataBufferSize];
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
In ReceiveCallback():
private void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
int byteLength = stream.EndRead(asyncResult);
if (byteLength <= 0)
{
// Disconnect client
return;
}
// Transfer data from receiveBuffer to data variable for handling
byte[] data = new byte[byteLength];
Array.Copy(receiveBuffer, data, byteLength);
// Handle data in any way you want to
// BeginRead again so you can keep receiving data
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
catch (Exception e)
{
Console.WriteLine($"Error receiving TCP data: {e.Message}");
}
}
I got this information from this tutorial.
I have written code for TcpListener in c# which is supposed to receive request from client socket and process the request (send the processed request to our another web service to get final response) then parse the response and send the response back to client socket which initiated the request.
Code snippet below.
Code works fine when receive few requests at a time but now in order to move this to cloud and accept multiple request. We are testing this functionality by running JMeter test on same.
We are getting throughput like 4 when we hit 100 threads per seconds (end to end test - client system to server socket to our web service and back) which should be at least 30 to match client requirement.
If we omit the end to end flow and just send back to hardcode response from server socket itself we are seeing throughput 700.
To find the root cause I have added delay while sending hardcore response (same which we need to communicate with our web service) and I can see same behavior i.e. throughput drastically downgrades = 4/3.8
It means when TcpListener is busy processing existing request it may not attend the next requests (may be I am wrong in assumption - please correct if so)
Please have a look at code and help me increasing the performance .
public void StartTCPServer()
{
Logger.Write_Info_Log("In StartTCPServer - inPort : " + AESDK_CONFIG.PORT_NO, 1, log);
try
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, AESDK_CONFIG.PORT_NO);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception Ex)
{
Logger.Write_Fatal_Log("Exception in Start Listening : " + Ex.Message, 1, log);
}
}
public void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public void ReadCallback(IAsyncResult ar)
{
String strdata = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
strdata = state.sb.ToString();
if (!string.IsNullOrEmpty(strdata))
{
// All the data has been read from the client.
if (strdata.Contains("<<CheckConnection>>"))
{
log.Info(GlobalVar.gThreadNo(GlobalVar.gintCurrentThread) + "Data Received: " + strdata);
byte[] byData1 = System.Text.Encoding.UTF8.GetBytes("<<CheckConnectionAlive>>");
Send(handler, "<<CheckConnectionAlive>>");
}
else
{
Interlocked.Increment(ref m_clientCount);
//Process incoming requests here and send response back to client
string strResponse = GetRequest(strdata, m_clientCount);
Send(handler, strResponse);
}
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I'm working on a UWP application which should communicate via TCP/UDP to a remote device. My issue is that the UWP app successfully sends UDP messages to the remote device, but does not receive the replies.
Here follows the code extracted from the app (simplified):
async Task TestUdpIP()
{
// Writer to the DatagramSocket
DataWriter writer;
using (var udpClient = new DatagramSocket())
{
try
{
// UDP Socket binding
udpClient.MessageReceived += UdpClient_MessageReceived;
var controllerName = new Windows.Networking.HostName(controllerIpAddress.ToString());
await udpClient.BindEndpointAsync(controllerName, controllerIpPort.ToString());
var remoteHostName = new Windows.Networking.HostName(hostIpAddres.ToString());
await udpClient.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Create a message to send
string message = "Some message";
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpClient.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(5000);
}
catch
{
}
}
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
However the UdpClient_MessageReceived handler does not fire. I'm sure that UDP messages are correctly sent from the UWP app and that the remote device replies back as shown in the following screenshot from Wireshark (the test has been taken on the same PC where the UWP app is running)
.
(IP Address, Port) details are shown in the following list to better explain the picture above
UWP application: (192.168.1.108, 19000) to send and receive.
Remote device: (192.168.1.152, 15999) to receive and (192.168.1.152, 54697) to send
Note: this is a similar question, where the answer says that for whatever reason the DatagramSocket should fire some messages before being able to receive. In my example a message is sent out however the message received handler does not fire anyway.
Note: The UWP app has been granted the internet (client) and the internet (client and server) capabilities
Note: I've tried also this (more readable) approach to bind the inbound/outbound datagram socket on the UWP app obtaining the same results:
// UDP Socket binding
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
EndpointPair endpointpar = new EndpointPair(controllerName,
controllerIpPort.ToString(),
remoteHostName,
remoteHostPort.ToString());
udpClient.MessageReceived += UdpClient_MessageReceived;
await udpClient.ConnectAsync(endpointpar);
Where is the issue? Many thanks!
Please try to also add the Private Networks (Client & Server) capability in your app's manifest.
On other hand, you can try the Official DatagramSocket sample to see whether the both devices can communicate with each other.
After some experimenting, I came out with the idea of using two different DatagramSocket instances: one to send out UDP messages, and one to listen for incoming messages. With this code, I've been able to send UDP messages to the remote device (as before) and also I've been able to receive UDP messages from the remote device.
async Task TestUdpIP_DifferentPorts()
{
// Writer to the DatagramSocket
DataWriter writer;
// Inbound and outbound DatagramSocket
DatagramSocket udpListener = new DatagramSocket();
DatagramSocket udpSender = new DatagramSocket();
try
{
// String containing the serializaed message
string serializedMessage = "Some message";
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
// Bind listener
udpListener.MessageReceived += UdpClient_MessageReceived;
await udpListener.BindEndpointAsync(controllerName, controllerIpPort.ToString());
// Connect sender
await udpSender.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpSender.OutputStream);
writer.WriteString(JsonConvert.SerializeObject(message));
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(1000);
}
catch (Exception ex)
{
// Some exception handling
}
udpSender.Dispose();
udpListener.Dispose();
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
With this approach only the IP port (or service name) of the inbound listener needs to be specified. The framework will choose the next available outbound IP port.
Note: If I understand well the DatagramSocket.ConnectAsync(EndpointPair) documentation, the same DatagramSocket instance can be used to send and listen for incoming message, so I could not figure out the need for two different instances. From the documentation:
This ConnectAsync(EndPointPair) method on a DatagramSocket is used to define the local and remote endpoint where datagrams will be sent when using the OutputStream property. This method also restricts remote IP addresses of packets that will be accepted to the remote hostname in the endpointPair parameter. Only incoming packets that match the remote endpoint in the endpointPair parameter will trigger the MessageReceived event on the DatagramSocket.
I am deploying my application in Tandem System (Unix environment). I am trying to connect to other application using TCP. I have a IP adress and Port number. from client (my application), I am writing data, looks like it's working (Not getting any Exception) but while reading data, I am getting ReadTimeOutException. Below is my program, I will appreciate your help. There is the same application which is return is C++ it's working fine with the same IP Address and Port number
Socket clientSocket = new Socket();
clientSocket.setKeepAlive(true);
clientSocket.setReuseAddress(true);
clientSocket.setTcpNoDelay(true);
clientSocket.setSoTimeout(120000);
clientSocket.setSendBufferSize(65535);
clientSocket.connect(new InetSocketAddress("Server IP", "Port Number"), 1000);
OutputStream outstream = clientSocket.getOutputStream();
outstream .writeInt(msgLen);
dout.write(msg, 0, msgLen);
dout.flush();
DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
int len = din.readInt();
data = new byte[len];
dis .readFully(data);
Its Throwing an Error while reading it.
Timeout while attempting to establish socket connection.
java.net.SocketTimeoutException: Read timed out
===========================
Socket clientSocket = new Socket();
clientSocket.setKeepAlive(true);
clientSocket.setReuseAddress(true);
clientSocket.setTcpNoDelay(true);
clientSocket.setSoTimeout(120000); // Should wait 3 minutes before throwing time out exception - Actually throwing after 2 minutes
clientSocket.setSendBufferSize(65535);
InputStream in= new ObjectInputStream(socket.getInputStream());
OutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.write(byteArray);
out.flush();
// Receive the same string back from the server
int totalBytesRcvd = 0; // Total bytes received so far
int bytesRcvd; // Bytes received in last read
while (totalBytesRcvd < byteArray.length) {
if ((bytesRcvd = in.read(byteArray, totalBytesRcvd,
byteArray.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection close prematurely");
totalBytesRcvd += bytesRcvd;
}
clientSocket .close(); // Close the socket and its streams
Please help me with this problem, I am stuck on this since last week.
Thank you!!!!
It isn't throwing that exception 'while attempting to establish the connection'. It is throwing it at some read call, almost certainly inside the constructor for ObjectInputStream. You should have included the stack trace in your question.
You need to create the ObjectOutputStream before the ObjectInputStream.
12000 milliseconds is two minutes, not three.
You should use readFully() at the client, just like you're doing in the server.
I hava a socket server is written in Java and the client is written in C#.
If I use the InputStream in a socket server, I can get the request from the Client. My code as below:
InputStream myIN = sock.getInputStream();
byte[] b = new byte[10];
int revByte = myIN.read(b);
but if I use the ObjectInputStream in the socket server, I can not receive any request from the Client.The exception is: "java.io.StreamCorruptedException: invalid stream header"
My code as below:
in = new ObjectInputStream( sock.getInputStream() );
Object value = in.readObject();
So, my question is: can C# client work with ObjectInputStream in Java via socket?
Any helping will be appreciate.Thanks so much, Dan
ObjectInputStream expects a data stream containing serialized representations of java objects... theoretically c# could encode it's objects in java's serialization format, but it wouldn't be pretty.
jspcal is right: Maybe with these classes?
http://mediakey.dk/~cc/java-and-c-client-server-socket-programming/
Java Server
try
{
ServerSocket ss = new ServerSocket(1800);
Socket s = ss.accept();
System.out.println("Client Accepted");
BufferedReader br = new BufferedReader(new
InputStreamReader(s.getInputStream()));
System.out.println(br.readLine());
PrintWriter wr = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true);
wr.println("Welcome to Socket Programming");
}
catch(Exception e){ System.out.println(e); }
C# Client:
try
{
TcpClient tc = new TcpClient("server",1800);// in the place of server, enter your java server's hostname or Ip
Console.WriteLine("Server invoked");
NetworkStream ns = tc.GetStream();
StreamWriter sw = new StreamWriter(ns);
sw.WriteLine("My name is Pramod.A");
sw.Flush();
StreamReader sr = new StreamReader(ns);
Console.WriteLine(sr.ReadLine());
}
catch(Exception e){ Console.WriteLine(e); }