I'm Trying to create a code to send a TCP message to a server.
When I use AutoIT Script Language with this code:
Example()
Func Example()
Local $ConnectedSocket, $szData
Local $szIPADDRESS = "10.200.0.104"
Local $nPORT = 1040
; Start The TCP Services
TCPStartup()
; Initialize a variable to represent a connection
$ConnectedSocket = -1
;Attempt to connect to SERVER at its IP and PORT 1040
$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)
; If there is an error... show it
If #error Then
MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & #error)
Else
$szData="0x0021601FA10706052B0C00815ABE14281206072B0C00821D8148A007A0050303000800000DA20B0201013006020200D30500"
TCPSend($ConnectedSocket, $szData)
EndIf
EndFunc;==>Example
Works fine but I need to write the same code in C#. I try to do this:
private static byte[] MessageToByteArray(string message, Encoding encoding)
{
var byteCount = encoding.GetByteCount(message);
if (byteCount > byte.MaxValue)
throw new ArgumentException("Message size is greater than 255 bytes in the provided encoding");
var byteArray = new byte[byteCount + 1];
byteArray[0] = (byte)byteCount;
encoding.GetBytes(message, 0, message.Length, byteArray, 1);
return byteArray;
}
public static void Main(string[] args)
{
const string message = "0x0021601FA10706052B0C00815ABE14281206072B0C00821D8148A007A0050303000800000DA20B0201013006020200D30500";
var byteArray = MessageToByteArray(message, Encoding.ASCII);
Socket m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse("10.200.0.104");
System.Net.IPEndPoint remoteEP = new IPEndPoint(ipAdd, 1040);
m_socClient.Connect(remoteEP);
try
{
m_socClient.Send(byteArray);
}
catch (SocketException se)
{
Console.WriteLine(se.Message.ToString());
}
}
But this code doesn't work. The server shows when he receives the command. With C# code, the server shows that have connected but the command doesn't execute.
Are you sure you have to prefix the length?
byteArray[0] = (byte)byteCount;
encoding.GetBytes(message, 0, message.Length, byteArray, 1);
Often you have a null-terminated string:
encoding.GetBytes(message, 0, message.Length, byteArray, 0);
byteArray[byteArray.Length - 1] = (byte)'\0';
Related
I have C# Client and C# Server Programs that connected with each other successfully and works fine. But when i want to connect C# Client with C++ server then C# client gets halted while C++ Server produces success messages of "winsock initialization success " and "creating socket success".
C++ Server Code
WSADATA wsaData;
struct sockaddr_in address_of_server;
struct sockaddr_in address_of_client;
int socket_of_client;
int size_of_address_of_client = sizeof(address_of_client);
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0) {
printf("winsock initialization success\n");
}
else {
printf("winsock initialization failure\n");
}
SOCKET socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
if (socket_of_server == -1) {
printf("creating socket failure\n");
}
else {
printf("creating socket success\n");
}
memset(&address_of_server, 0, sizeof(address_of_server));
address_of_server.sin_family = AF_INET;
//address_of_server.sin_family = PF_INET;
address_of_server.sin_addr.s_addr = htonl(INADDR_ANY);
address_of_server.sin_port = htons(8888);
bind(socket_of_server, (struct sockaddr*)&address_of_server, sizeof(address_of_server));
listen(socket_of_server, 5);
ClientSocket = accept(socket_of_server, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(socket_of_server);
WSACleanup();
return 1;
}
socket_of_client = accept(socket_of_server, (struct sockaddr*)&address_of_client, &size_of_address_of_client);
WSACleanup();
C# Client Code
public CCRMain()
{
InitializeComponent();
clientSocket.Connect("127.0.0.1", 8888);
}
void Data()
{
MainWindow mw = (MainWindow)Application.Current.MainWindow;
NetworkStream serverStream = mw.clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(A1G1.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)mw.clientSocket.ReceiveBufferSize);
System.IO.MemoryStream ms = new System.IO.MemoryStream(inStream);
System.IO.BinaryReader br = new System.IO.BinaryReader(ms);
int[] inComingData = new int[5];
for (int i = 0; i < 5; i++)
{
inComingData[i] = br.ReadInt32();
Debug.WriteLine(inComingData[i].ToString());
A1G1Text.Text = inComingData[0].ToString();
}
}
NetworkStream.Read() is blocking. So as long as the server does not close the connection, this will not return until 10025 bytes have been read.
You should directly read from the network stream, not copy it over twice (or even four times in your case: From network to inStream and then to a MemoryStream and then to inCommingData and then to your text variable).
Use the NetworkStream.ReadTimeout property to indicate that you want Read() to return even if not the entire buffer was filed within some time.
I am trying to connect my c# client to a node.js server via tls/ssl. The Server is working and I have created my certs. But If I want to connect via TcpClient to the Server, it says, that the Certificate is invalid. Could you make your own validation for that cert? Do you guys have any ideas?
namespace Client
{
class Program
{
private static TcpClient _TcpClient = new TcpClient("localhost", 8000);
private static SslStream stream;
static void Main(string[] args)
{
stream = new SslStream(_TcpClient.GetStream());
stream.AuthenticateAsClient("localhost");
byte[] buffer = new byte[2048];
StringBuilder data = new StringBuilder();
int bytes = -1;
do
{
bytes = stream.Read(buffer, 0, buffer.Length);
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
data.Append(chars);
if (data.ToString().IndexOf("<EOF>") != -1)
{
break;
}
}
while (bytes != 0);
Console.WriteLine(data.ToString());
Console.ReadKey();
}
}
}
The Certificate is self signed so I have to send it with the client, but I dont know how. Even if I disable the validation via ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
, it does not work (I just put it in the first line of the main method).
So, I just didn't change the code, I just installed the certificate on my server with this guide: https://technet.microsoft.com/en-us/library/ff730672.aspx
i have an issue where im not receiving any bytes from the connected TcpClient!
Server: (i attempt to add the received message into a listbox, but nothing comes out.
//tl is a TcpListener
//I set this up in a 500 milisecond loop. No worries about that.
if (tl.Pending())
{
TcpClient tcp = tl.AcceptTcpClient();
var s = tcp.GetStream();
int bytesRead = s.Read(new byte[tcp.ReceiveBufferSize], 0,
tcp.ReceiveBufferSize);
string dataReceived = Encoding.ASCII.GetString(new
byte[tcp.ReceiveBufferSize], 0, bytesRead);
listBox1.Items.Add(dataReceived);
tcp.Close();
oac++; //Overall connection count
label3.Text = "Overall Connections: " + oac; //logging connections
}
Client:
void Send(){
TcpClient c = new TcpClient(Im not including my ip., 4444);
System.IO.StreamWriter w = new System.IO.StreamWriter(c.GetStream());
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes($"Username: \"
{textBox1.Text}\" | Password: \"{textBox2.Text}\"");
NetworkStream nwStream = c.GetStream();
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
nwStream.Flush();
}
I The connection works, but theres some issues receiving data. it just comes out blank
On serverside, your problem is that you renew toy byte array new byte[tcp.ReceiveBufferSize]. You could also do something like this:
using( var inputStream = new MemoryStream() )
{
tcp.GetStream().CopyTo(inputStream);
Encoding.ASCII.GetString(inputStream.ToArray());
listBox1.Items.Add(dataReceived);
...
}
Remember using on all IDisposable's, else you will run out of resources.
I am using Network Stream, TcpListener and Sockets.
I want to make sure that all the data from sender is received by receiver.
I have below code for receiver
private void StartReciever()
{
util.LoadSettings();
string tcpIpAddress = util.svrSettings["IpAddress"];
string port = util.svrSettings["Port"];
string outDir = util.svrSettings["isOutput"];
new Thread(
() =>
{
if (!File.Exists(util.settingFile))
Logger("Please setup the services first.");
else
{
try
{
IPAddress ipAddress = IPAddress.Parse(tcpIpAddress);
TcpListener tcpListener = new TcpListener(ipAddress, Convert.ToInt32(port));
tcpListener.Start();
Logger("\nWaiting for a client to connect...");
//blocks until a client connects
Socket socketForClient = tcpListener.AcceptSocket();
Logger("\nClient connected");
//Read data sent from client
NetworkStream networkStream = new NetworkStream(socketForClient);
int bytesReceived, totalReceived = 0;
string fileName = "testing.txt";
byte[] receivedData = new byte[10000];
do
{
bytesReceived = networkStream.Read
(receivedData, 0, receivedData.Length);
totalReceived += bytesReceived;
Logger("Progress of bytes recieved: " + totalReceived.ToString());
if (!File.Exists(fileName))
{
using (File.Create(fileName)) { };
}
using (var stream = new FileStream(fileName, FileMode.Append))
{
stream.Write(receivedData, 0, bytesReceived);
}
}
while (bytesReceived != 0);
Logger("Total bytes read: " + totalReceived.ToString());
socketForClient.Close();
Logger("Client disconnected...");
tcpListener.Stop();
}
catch (Exception ex)
{
// Error : "Only one usage of each socket address (protocol/network address/port) is normally permitted"
Logger("There is some error: " + ex.Message);
}
}
}).Start();
}
How can I make sure that my code after do-while loop executes ?
Sender Code:
private static void SendData(string tcpIpAddress, string port, string filename)
{
new Thread(
() =>
{
TcpClient tcpClient = new TcpClient(tcpIpAddress, Convert.ToInt32(port));
//const int bufsize = 8192;
const int bufsize = 10000;
var buffer = new byte[bufsize];
NetworkStream networkStream = tcpClient.GetStream();
using (var readFile = File.OpenRead(filename))
{
int actuallyRead;
while ((actuallyRead = readFile.Read(buffer, 0, bufsize)) > 0)
{
networkStream.Write(buffer, 0, actuallyRead);
}
}
}).Start();
}
How can I make sure that my code after do-while loop executes?
Here, it's easy because you can close the connection on the sender which will cause the receiver to read zero bytes and terminate the loop.
In fact you forgot to clean up the sender. Dispose of all resources. This fixes the problem.
Your code would benefit from the Code Review SE. I see about a dozen issues immaterial to this question. Would be a great way for you to improve yourself.
For example you can replace the copy loops with Stream.Copy.
The usual way I've seen this done to prepend the data being sent with the number of bytes about to be sent. That way the receiver knows that the packet has been read. Even if the network gets interrupted or the sender sends something else without a break.
Note that doing this you can also read the first 8 bytes (or 4 if an Int32 will do the job) before allocating the read buffer which can help optimise the buffer size
Another common way of doing it is with a specific terminator, but then you have to guarantee that whatever you're sending cannot contain that terminator
I have a socket server and am trying to receive a string from the client.
The client is perfect and when I use this
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine(k);
Console.WriteLine("Recieved...");
for (int i = 0; i < k; i++) {
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
}
All is okay and I get my string in the console.
But how can I get now my receive into a string so I can use it in a switch case?
Like this:
string action = Convert.ToChar(b[i]);
Error:
The Name i isn't in the current context.
its the only Error Message i get.
This way no need set buffer size, it fits to response:
public static byte[] ReceiveAll(this Socket socket)
{
var buffer = new List<byte>();
while (socket.Available > 0)
{
var currByte = new Byte[1];
var byteCounter = socket.Receive(currByte, currByte.Length, SocketFlags.None);
if (byteCounter.Equals(1))
{
buffer.Add(currByte[0]);
}
}
return buffer.ToArray();
}
Assuming s is a Socket object on which you call receive, you get an byte[] back. To convert this back to a string, use the appropiate encoding, e.g.
string szReceived = Encoding.ASCII.GetString(b);
Edit: Since the buffer b is always 100 bytes, but the actual number of bytes received varies with each connection, one should use the return value of the Socket.Receive() call to only convert the actual number of received bytes.
byte[] b = new byte[100];
int k = s.Receive(b);
string szReceived = Encoding.ASCII.GetString(b,0,k);
Init socket
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdd = System.Net.IPAddress.Parse(m_ip);
IPEndPoint remoteEP = new IPEndPoint(ipAdd, m_port);
Connect socket
socket.Connect(remoteEP);
Receive from socket
byte[] buffer = new byte[1024];
int iRx = socket.Receive(buffer);
char[] chars = new char[iRx];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(buffer, 0, iRx, chars, 0);
System.String recv = new System.String(chars);
Send message
byte[] byData = System.Text.Encoding.ASCII.GetBytes("Message");
socket.Send(byData);
Close socket
socket.Disconnect(false);
socket.Close();