I'm trying to send a packet using httpclient
TcpClient tc = new TcpClient(ip, 4500);
string s = "A7007000601D3B00";
byte[] arr = new byte[s.Length/2];
for ( var i = 0 ; i<arr.Length ; i++ ){
arr[i] = (byte)Convert.ToInt32(s.Substring(i*2,2), 16);
}
NetworkStream stream = tc.GetStream();
stream.Write(arr, 0, arr.Length);
tc.Close();
The problem is that it sends from port 47109, however i need to send the packet using port 46324. How do i set this?
There is an overload of the TcpClient constructor that allows you to bind it to a specific local IP address and port. See the documentation on MSDN.
The reason the example at Is there a way to specify the local port to used in tcpClient? is not working is probably because the first address on the list is not actually the local machine ip address. Something like this might fix the issue and pull the proper local IP address:
string remoteIP = "x.x.x.x";
IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).First();
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 47109);
TcpClient clientSocket = new TcpClient(ipLocalEndPoint);
clientSocket.Connect(remoteIP, 4500);
Related
I'm trying to communicate with a modbus device in my network at ip 192.168.1.76. My host computer address is 192.168.1.132. I'm not able to connect to or listen to device ip.
basically i'm using NModbus4 library. I've created a ModbusTCPSlave and attached the tcp listener to it. then i assigned ModbusSlaveRequestReceived event to that slave. but it gives nothing in return when i try to change register values directly from Modscan software.
Main()
{
var masterEndpoint = new IPEndPoint(IPAddress.Parse("192.168.1.132"), 502);
var listener = new TcpListener(IPAddress.Any, 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, new TcpListener(masterEndpoint), 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();
}
private static void Modbus_Request_Event(object sender, Modbus.Device.ModbusSlaveRequestEventArgs e)
{
//disassemble packet from master
byte fc = e.Message.FunctionCode;
byte[] data = e.Message.MessageFrame;
byte[] byteStartAddress = new byte[] { data[3], data[2] };
byte[] byteNum = new byte[] { data[5], data[4] };
Int16 StartAddress = BitConverter.ToInt16(byteStartAddress, 0);
Int16 NumOfPoint = BitConverter.ToInt16(byteNum, 0);
Console.WriteLine(fc.ToString() + "," + StartAddress.ToString() + "," + NumOfPoint.ToString());
}
I expect to get function code, start address and number of points in console application when any register value is changed
I copied your code. Changed the IP address to my "server" and it worked.
So, the issue you are having is either in the setup of your "server" or in the PLC program.
I thought that I had to do some port forwarding on my router. I did not. It did not make a difference.
Server setup:
Your "server"'s IP address needs to be static. Whether your 'server' is your development system or not. And don't forget when you deploy... Server's IP address has to be static as well (not that it wouldn't be...just saying)
Add an inbound Firewall rule to allow connections to the port, in this case 502, otherwise you'll have to allow access every time you launch/start a test.
PLC program
I am using Click PLC's by Koyo. Not sure if this is the rule for all PLC's or not; but, we had to add a line of code to "write" the values we wanted to pick up off the TCP stream. Without the write, the PLC was not sending out a request to join the TcpListener.
Last:
The code to start your listener only needs to be this:
var listener = new TcpListener(IPAddress.Parse("192.168.1.244"), 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, listener, 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();
My client isn't able to connect to the irc server I am trying to connect to. I did some research and it says that I need to listen on port 113 and respond back to the server in a certain format. I am not sure exactly how to do this. When I tried doing it before I got an error message. Here is the code before I tried listening. The irc sends the message to my client "No ident response". Do I need to create an entire different all together that will listen respond on port 113 or can I do it in here?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ConnectIRC
{
class Program
{
static void Main(string[] args)
{
string ip = "asimov.freenode.net";
string nick = " NICK IKESBOT \r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
for(;;){
byte[] buffer = new byte[3000];
int rec = conn.Receive(buffer, 0, buffer.Length, 0);
Array.Resize(ref buffer, rec);
Console.WriteLine(Encoding.Default.GetString(buffer));
}
}
}
}
Despite #Saruman's answer above, you don't need to create an ident server to connect to most IRC networks (including freenode). You can completely ignore the error about "No ident response". It's an outdated technology which is no longer secure and only ever worked properly on Unix-based multiuser systems.
Your actual issue appears to be that you never finish registering the connection to the IRC server. The specification states that you need to send both USER and NICK messages:
string ip = "asimov.freenode.net";
string nick = "NICK IKESBOT \r\n";
// format is: USER <username> * * :<realname>
string user = "USER IKESBOT * * :IKESBOT\r\n";
string join = "JOIN #NetChat\r\n";
int port = 6667;
const int recvBufSize = 8162;
byte[] recvbBuf = new byte[recvBufSize];
//stores the nick
byte[] nickBuf = Encoding.ASCII.GetBytes(nick);
byte[] userBuf = Encoding.ASCII.GetBytes(user);
//Stores the room join
byte[] joinBuf = Encoding.ASCII.GetBytes(join);
Socket conn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
conn.Connect(ip, port);
conn.Send(nickBuf, nickBuf.Length, SocketFlags.None);
conn.Send(userBuf, userBuf.Length, SocketFlags.None);
conn.Send(joinBuf, joinBuf.Length, SocketFlags.None);
(You've got an extra space before the NICK - this may or may not break things.)
Aside:
You may find it easier to use TcpClient, StreamReader and StreamWriter to access the underlying socket - they wrap it and deal with the buffers for you. You can then read the response line by line directly into a string, and write to the socket by just passing a string. No fiddling around with encoding and buffers.
TcpClient client = new TcpClient("chat.freenode.net", 6667);
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
string recievedData = reader.ReadLine();
writer.WriteLine("NICK IKESBOT");
writer.Flush();
Yes you will need to create a totally separate port to listen on and respond back to ident requests
More information on ident can be found here
I'm using Xamarin + MonoTouch on iOS to browse for a web server on the network that I can then download files from.
The NSNetService that is passed into the resolve event handler contains addresses as NSData. I can't find a good way to turn that NSData into an actual IP address that I can then build a URL from, i.e. http:// < IPAddress > /folder/file.htm
This is my NSNetService.AddressResolved event handler:
private void OnServiceResolved(object sender, EventArgs args)
{
NSNetService service = (NSNetService)sender;
// service.Port is valid.
// service.HostName is valid.
// but we want the IP addres, which is in service.Addresses.
// None of the following four methods works quite right.
IPAddress address = (IPAddress)service.Addresses [0]; // Cannot convert type NSData to IPAddress
SocketAddress address2 = (SocketAddress)service.Addresses[0]; // Cannot convert NSData to SocketAddress. A binary copy might work?
IPHostEntry entry = (IPHostEntry)service.Addresses [0]; // Cannot convert NSData to IPHostEntry
IPHostEntry entry2 = Dns.GetHostByName (service.HostName); // This kinda works, but is dumb. Didn't we just resolve?
}
What's the right way to get the IP address of the service from an NSNetService in a resolve event?
The NSNetService.Addresses property gives you NSData instances which must be converted into something that IPAddress (or other .NET types) can digest. E.g.
MemoryStream ms = new MemoryStream ();
(ns.Addresses [0] as NSData).AsStream ().CopyTo (ms);
IPAddress ip = new IPAddress (ms.ToArray ());
Note that this can return you an IPv6 address (or format that IPAddress won't accept). You might want to iterate all the Addresses to find the best one.
I'll look into adding a convenience method into future versions of Xamarin.iOS.
UPDATE
A more complete version, that returns an IPAddress, would look like:
static IPAddress CreateFrom (NSData data)
{
byte[] address = null;
using (MemoryStream ms = new MemoryStream ()) {
data.AsStream ().CopyTo (ms);
address = ms.ToArray ();
}
SocketAddress sa = new SocketAddress (AddressFamily.InterNetwork, address.Length);
// do not overwrite the AddressFamily we provided
for (int i = 2; i < address.Length; i++)
sa [i] = address [i];
IPEndPoint ep = new IPEndPoint (IPAddress.Any, 0);
return (ep.Create (sa) as IPEndPoint).Address;
}
I'm using an UdpClient to read data from a multicast group.
It's configured like this:
m_udpClientReceiver = new UdpClient();
m_receivingEndPoint = new IPEndPoint(IPAddress.Any, m_port);
m_udpClientReceiver.ExclusiveAddressUse = false;
m_udpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
m_udpClientReceiver.ExclusiveAddressUse = false;
m_udpClientReceiver.Client.Bind(m_receivingEndPoint);
m_udpClientReceiver.JoinMulticastGroup(m_multicastAddress, 255);
and I read it with:
Byte[] data = m_udpClientReceiver.Receive(ref m_receivingEndPoint);
I've several network cards(two LAN, one wifi), that are bound on differents subnets. I need to know on which network card(which ip in fact) the request has been received.
How can I achieve this?
Thank you!
As an alternative have you considered not joining a multicast group? You can send and receive multicast packets just as easily using the standard UDPClient class. i.e.
UdpClient.Send(byte[] dgram, int bytes, IPEndPoint endPoint)
where endPoint = new IPEndPoint(IPAddress.Broadcast, <port number>). And on the receive still using:
Byte[] data = m_udpClientReceiver.Receive(ref m_receivingEndPoint);
where m_receivingEndPoint is now correctly set? I've just tested this and it works fine.
I'm finally using the BeginReceive method(async), and I'm giving as context the ip on which it's bound
I have a game server (WoW).
I want my players to download my custom patches to the game.
I've done a program that checks for update/downloading things.
I want my program to send a packet to my game server if player have all my patches. I dont need any response from the server, it will handle it, but its another story.
So I want to know, how to send a packet to a server.
Thank you!
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPAddress serverAddr = IPAddress.Parse("192.168.2.255");
IPEndPoint endPoint = new IPEndPoint(serverAddr, 11000);
string text = "Hello";
byte[] send_buffer = Encoding.ASCII.GetBytes(text );
sock.SendTo(send_buffer , endPoint);
static void SendUdp(int srcPort, string dstIp, int dstPort, byte[] data)
{
using (UdpClient c = new UdpClient(srcPort))
c.Send(data, data.Length, dstIp, dstPort);
}
Usage:
SendUdp(11000, "192.168.2.255", 11000, Encoding.ASCII.GetBytes("Hello!"));