{"id":36924091,"url":"https://github.com/derek-will/SocketCANSharp","last_synced_at":"2026-01-19T18:00:41.244Z","repository":{"id":50277372,"uuid":"442606232","full_name":"derek-will/SocketCANSharp","owner":"derek-will","description":".NET managed wrapper for SocketCAN on Linux","archived":false,"fork":false,"pushed_at":"2025-02-22T19:41:00.000Z","size":432,"stargazers_count":76,"open_issues_count":12,"forks_count":17,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2025-12-21T09:22:02.120Z","etag":null,"topics":["automotive","c-sharp","can-bus","can-fd","can-gateway","can-xl","industrial-automation","iso-tp","j1939","linux"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/derek-will.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-12-28T23:11:43.000Z","updated_at":"2025-11-26T07:00:56.000Z","dependencies_parsed_at":"2024-09-08T17:28:08.622Z","dependency_job_id":"6a046b25-25cc-454f-ae8c-1f0564de9309","html_url":"https://github.com/derek-will/SocketCANSharp","commit_stats":{"total_commits":94,"total_committers":2,"mean_commits":47.0,"dds":"0.010638297872340385","last_synced_commit":"68809d816d5e4a814b4400d276ef516390491579"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/derek-will/SocketCANSharp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derek-will%2FSocketCANSharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derek-will%2FSocketCANSharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derek-will%2FSocketCANSharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derek-will%2FSocketCANSharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/derek-will","download_url":"https://codeload.github.com/derek-will/SocketCANSharp/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derek-will%2FSocketCANSharp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28578952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T17:42:58.221Z","status":"ssl_error","status_checked_at":"2026-01-19T17:40:54.158Z","response_time":67,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automotive","c-sharp","can-bus","can-fd","can-gateway","can-xl","industrial-automation","iso-tp","j1939","linux"],"created_at":"2026-01-12T19:00:25.486Z","updated_at":"2026-01-19T18:00:41.232Z","avatar_url":"https://github.com/derek-will.png","language":"C#","readme":"[![NuGet](https://img.shields.io/nuget/v/SocketCANSharp.svg)](https://www.nuget.org/packages/SocketCANSharp)\n[![NuGet](https://img.shields.io/nuget/dt/SocketCANSharp.svg)](https://www.nuget.org/packages/SocketCANSharp)\n\n## SocketCAN# (SocketCANSharp)\n\nThis repository contains a .NET managed wrapper for the Linux CAN subsystem (aka SocketCAN). This includes the wrapper library implementation, unit tests, and some example code.\n\nUsing this library you can either use the higher level classes or the lower level libc P/Invoke calls directly. \n\nThe classes such as `CanNetworkInterface`, `RawCanSocket`, and `IsoTpCanSocket` provide a simpler interface via object-oriented abstraction. This approach should be familiar to developers acquainted with C# and other higher level languages. Invoking the libc calls will be easier to those who prefer or are more familiar with C style (procedural) programming. This approach should also ease the process of porting over code written in C.\n\n#### Feature Chart\n\n| Feature                          | Kernel | SocketCAN#                | \n|:---------------------------------|:-------|:--------------------------|\n| Raw CAN Socket                   | 2.6.25 | 0.1[^2], 0.5              | \n| BCM Socket                       | 2.6.25 | 0.1[^2][^1], 0.8[^4], 0.9 |\n| ISO-TP (ISO 15765-2) Socket      | 5.10   | 0.1[^2], 0.3              | \n| SAE J1939 Socket                 | 5.4    | 0.1[^2], 0.8              |\n| CAN Network Interface Query[^5]  | 2.6.25 | 0.2, 0.13                 |\n| CAN Network Interface Attributes | 2.6.31 | 0.10[^3], 0.13            |\n| CAN-to-CAN Gateway               | 3.2    | 0.11                      |\n| Classical CAN                    | 2.6.25 | 0.1                       |\n| CAN FD                           | 3.6    | 0.1                       |\n| CAN XL                           | 6.2    | 0.12                      |\n| CAN XL VCID                      | 6.9    | 0.12                      |\n| epoll API                        | 2.5.44 | 0.4[^1], 0.8[^4]          |\n| Capabilities API                 | 2.2    | 0.11                      |\n\n[^1]: 64-bit process support only\n[^2]: Low-level API only \n[^3]: Read-only\n[^4]: Added 32-bit process support\n[^5]: Interface name-based search until 0.13 where it becomes a type-based search\n\n### Raw CAN Support\n\n#### Object-Oriented Style\n```cs\nCanNetworkInterface vcan0 = CanNetworkInterface.GetAllInterfaces(true).First(iface =\u003e iface.Name.Equals(\"vcan0\"));\n\nusing (var rawCanSocket = new RawCanSocket())\n{\n    rawCanSocket.Bind(vcan0);\n    int bytesWritten = rawCanSocket.Write(new CanFrame(0x123, new byte[] { 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }));\n    int bytesRead = rawCanSocket.Read(out CanFrame frame);\n}\n```\n\n#### Procedural Style\n```cs\nusing (SafeFileDescriptorHandle socketHandle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Raw, SocketCanProtocolType.CAN_RAW))\n{\n    var ifr = new Ifreq(\"vcan0\");\n    int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);\n\n    var addr = new SockAddrCan(ifr.IfIndex);\n    int bindResult = LibcNativeMethods.Bind(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));\n\n    var writeFrame = new CanFrame(0x123, new byte[] { 0x11, 0x22 });\n    int nWriteBytes = LibcNativeMethods.Write(socketHandle, ref writeFrame, Marshal.SizeOf(typeof(CanFrame)));\n\n    var readFrame = new CanFrame();\n    int nReadBytes = LibcNativeMethods.Read(socketHandle, ref readFrame, Marshal.SizeOf(typeof(CanFrame)));\n}\n```\n\n### ISO 15765-2 (ISO-TP) Support\n\n#### Object-Oriented Style\n```cs\nCanNetworkInterface vcan0 = CanNetworkInterface.GetAllInterfaces(true).First(iface =\u003e iface.Name.Equals(\"vcan0\"));\n\nusing (var testerSocket = new IsoTpCanSocket())\n{\n    testerSocket.BaseOptions = new CanIsoTpOptions()\n    {\n        Flags = IsoTpFlags.CAN_ISOTP_TX_PADDING | IsoTpFlags.CAN_ISOTP_WAIT_TX_DONE,\n    };\n\n    testerSocket.Bind(vcan0, 0x600, 0x700);\n    int bytesWritten = testerSocket.Write(new byte[] { 0x3e, 0x00 });\n    var receiveBuffer = new byte[4095];\n    int bytesRead = testerSocket.Read(receiveBuffer);\n}\n```\n\n#### Procedural Style\n```cs\nusing (SafeFileDescriptorHandle testerSocketHandle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Dgram, SocketCanProtocolType.CAN_ISOTP))\n{\n    var ifr = new Ifreq(\"vcan0\");\n    int ioctlResult = LibcNativeMethods.Ioctl(testerSocketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);\n\n    var testerAddr = new SockAddrCanIsoTp(ifr.IfIndex)\n    {\n        TxId = 0x600,\n        RxId = 0x700,\n    };\n    int bindResult = LibcNativeMethods.Bind(testerSocketHandle, testerAddr, Marshal.SizeOf(typeof(SockAddrCanIsoTp)));\n\n    var requestMessage = new byte[] { 0x3e, 0x00 };\n    int nBytes = LibcNativeMethods.Write(testerSocketHandle, requestMessage, requestMessage.Length);\n    var receiveResponseMessage = new byte[4095];\n    nBytes = LibcNativeMethods.Read(testerSocketHandle, receiveResponseMessage, receiveResponseMessage.Length);\n}\n```\n\n### SAE J1939 Support\n\n#### Object-Oriented Style\n```cs\nvar vcan0 = CanNetworkInterface.GetAllInterfaces(true).FirstOrDefault(iface =\u003e iface.Name.Equals(\"vcan0\"));\n\nusing (var j1939Socket = new J1939CanSocket())\n{\n    j1939Socket.EnableBroadcast = true;\n    j1939Socket.SendPriority = 3;\n    j1939Socket.Bind(vcan0, SocketCanConstants.J1939_NO_NAME, 0x0F004, 0x01);\n    var destAddr = new SockAddrCanJ1939(vcan0.Index)\n    {\n        Name = SocketCanConstants.J1939_NO_NAME,\n        PGN = 0x0F004,\n        Address = SocketCanConstants.J1939_NO_ADDR,\n    };\n    j1939Socket.WriteTo(new byte[] { 0xFF, 0xFF, 0xFF, 0x6C, 0x50, 0xFF, 0xFF, 0xFF }, MessageFlags.None, destAddr);\n}\n```\n\n#### Procedural Style\n```cs\nusing (var j1939Handle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Dgram, SocketCanProtocolType.CAN_J1939))\n{\n    var ifr = new Ifreq(\"vcan0\");\n    int ioctlResult = LibcNativeMethods.Ioctl(j1939Handle, SocketCanConstants.SIOCGIFINDEX, ifr);\n\n    int value = 1;\n    int enableBroadcastResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_SOCKET, SocketLevelOptions.SO_BROADCAST, ref value, Marshal.SizeOf(typeof(int)));\n\n    int prio = 3;\n    int prioResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_CAN_J1939, J1939SocketOptions.SO_J1939_SEND_PRIO, ref prio, Marshal.SizeOf(typeof(int)));\n\n    var srcAddr = new SockAddrCanJ1939(ifr.IfIndex)\n    {\n        Name = SocketCanConstants.J1939_NO_NAME,\n        PGN = 0x0F004,\n        Address = 0x01,\n    };\n    int bindResult = LibcNativeMethods.Bind(j1939Handle, srcAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));;\n\n    var dstAddr = new SockAddrCanJ1939(vcan0.Index)\n    {\n        Name = SocketCanConstants.J1939_NO_NAME,\n        PGN = 0x0F004,\n        Address = SocketCanConstants.J1939_NO_ADDR,\n    };\n    byte[] data = new byte[] { 0xFF, 0xFF, 0xFF, 0x34, 0x12, 0xFF, 0xFF, 0xFF };\n    int sendToResult = LibcNativeMethods.SendTo(j1939Handle, data, data.Length, MessageFlags.None, dstAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));\n}\n```\n\n### Broadcast Manager (BCM) Support\n\n#### Object-Oriented Style\n```cs\nCanNetworkInterface vcan0 = CanNetworkInterface.GetAllInterfaces(true).First(iface =\u003e iface.Name.Equals(\"vcan0\"));\n\nusing (var bcmCanSocket = new BcmCanSocket())\n{\n    bcmCanSocket.Connect(vcan0);\n    var canFrame = new CanFrame(0x333, new byte[] { 0xDE, 0xAD, 0xBE, 0xEF });\n    var frames = new CanFrame[] { canFrame };\n    var config = new BcmCyclicTxTaskConfiguration()\n    {\n        Id = 0x333,\n        StartTimer = true,\n        SetInterval = true,\n        InitialIntervalConfiguration = new BcmInitialIntervalConfiguration(10, new BcmTimeval(0, 5000)), // 10 messages at 5 ms\n        PostInitialInterval = new BcmTimeval(0, 100000), // Then at 100 ms\n    };\n    int nBytes = bcmCanSocket.CreateCyclicTransmissionTask(config, frames);\n}\n```\n\n#### Procedural Style\n```cs\nusing (SafeFileDescriptorHandle socketHandle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Dgram, SocketCanProtocolType.CAN_BCM))\n{\n    var ifr = new Ifreq(\"vcan0\");\n    int ioctlResult = LibcNativeMethods.Ioctl(socketHandle, SocketCanConstants.SIOCGIFINDEX, ifr);\n\n    var addr = new SockAddrCan(ifr.IfIndex);\n    int connectResult = LibcNativeMethods.Connect(socketHandle, addr, Marshal.SizeOf(typeof(SockAddrCan)));\n\n    if (Environment.Is64BitProcess)\n    {\n        var canFrame = new CanFrame(0x333, new byte[] { 0xDE, 0xAD, 0xBE, 0xEF });\n        var header = new BcmMessageHeader(BcmOpcode.TX_SETUP)\n        {\n            CanId = 0x333,\n            Flags = BcmFlags.SETTIMER | BcmFlags.STARTTIMER,\n            Interval1Count = 10, // 10 messages\n            Interval1 = new BcmTimeval(0, 5000), // at 5 ms interval\n            Interval2 = new BcmTimeval(0, 100000), // then at 100 ms\n            NumberOfFrames = 1,\n        };\n\n        var bcmMessage = new BcmCanMessage(header, new CanFrame[] { canFrame });\n        int nBytes = LibcNativeMethods.Write(socketHandle, bcmMessage, Marshal.SizeOf(bcmMessage));\n    }\n    else // 32-bit process\n    {\n        var canFrame = new CanFrame(0x333, new byte[] { 0xDE, 0xAD, 0xBE, 0xEF });\n        var header = new BcmMessageHeader32(BcmOpcode.TX_SETUP)\n        {\n            CanId = 0x333,\n            Flags = BcmFlags.SETTIMER | BcmFlags.STARTTIMER,\n            Interval1Count = 10, // 10 messages\n            Interval1 = new BcmTimeval(0, 5000), // at 5 ms interval\n            Interval2 = new BcmTimeval(0, 100000), // then at 100 ms\n            NumberOfFrames = 1,\n        };\n\n        var bcmMessage = new BcmCanMessage32(header, new CanFrame[] { canFrame });\n        int nBytes = LibcNativeMethods.Write(socketHandle, bcmMessage, Marshal.SizeOf(bcmMessage));\n    }\n}\n```\n\n### CAN Gateway (CGW) Support\n```cs\nvar vcan0 = CanNetworkInterface.GetAllInterfaces(true).FirstOrDefault(iface =\u003e iface.Name.Equals(\"vcan0\"));\nvar vcan1 = CanNetworkInterface.GetAllInterfaces(true).FirstOrDefault(iface =\u003e iface.Name.Equals(\"vcan1\"));\n\nusing (var cgwSocket = new CanGatewaySocket())\n{\n    cgwSocket.ReceiveTimeout = 1000;\n    cgwSocket.SendTimeout = 1000;\n    cgwSocket.Bind(new SockAddrNetlink(0, 0));\n    var rule = new CgwCanToCanRule(CgwCanFrameType.ClassicalCAN)\n    {\n        SourceIndex = (uint)vcan0.Index,\n        DestinationIndex = (uint)vcan1.Index,\n        EnableLocalCanSocketLoopback = true,\n        ReceiveFilter = new CanFilter(0x123, 0x7FF),\n        SetModifier = new ClassicalCanGatewayModifier(CanGatewayModificationType.CGW_MOD_LEN, new CanFrame(0x000, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 })),\n        ChecksumXorConfiguration = new CgwChecksumXor(0, 3, 4, 0xCC),\n        UpdateIdentifier = 0xFFEEEEDD,\n    };\n    cgwSocket.AddOrUpdateCanToCanRule(rule);\n    \n    var data = new byte[8192];\n    int bytesRead = cgwSocket.Read(data);\n    var realData = data.Take(bytesRead).ToArray();\n    NetlinkMessageHeader header = NetlinkUtils.PeekAtHeader(realData);\n    if (header.MessageType == NetlinkMessageType.NLMSG_ERROR)\n    {\n        NetlinkMessageError nlMsgErr = NetlinkMessageError.FromBytes(realData);\n        if (nlMsgErr.Error == 0)\n        {\n            Console.WriteLine(\"Successfully added CGW Rule!\");\n        }\n    }\n}\n```\n\n### CAN Network Interface Support\n```cs\nCanNetworkInterface can0 = CanNetworkInterface.GetAllInterfaces(false).First(iface =\u003e iface.Name.Equals(\"can0\"));\n\nConsole.WriteLine(\"Bringing Link Down...\");\ncan0.SetLinkDown();\n\nConsole.WriteLine(\"Configuring Interface...\");\ncan0.BitTiming = new CanBitTiming() { BitRate = 125000 };\ncan0.CanControllerModeFlags = CanControllerModeFlags.CAN_CTRLMODE_LOOPBACK | CanControllerModeFlags.CAN_CTRLMODE_ONE_SHOT;\ncan0.AutoRestartDelay = 5;\ncan0.MaximumTransmissionUnit = SocketCanConstants.CAN_MTU;\n\nConsole.WriteLine(\"Bringing Link Up...\");\ncan0.SetLinkUp();\n\nConsole.WriteLine(\"Reading Interface Properties...\");\nConsole.WriteLine($\"Inteface Device Flags: {can0.DeviceFlags}\");\nConsole.WriteLine($\"Inteface Operational Status: {can0.OperationalStatus}\");\nConsole.WriteLine($\"Controller State: {can0.CanControllerState}\");\nConsole.WriteLine($\"Auto-Restart Delay: {can0.AutoRestartDelay} ms\");\nConsole.WriteLine($\"Bit Timing: {can0.BitTiming.BitRate} bit/s\");\nConsole.WriteLine($\"Controller Mode Flags: {can0.CanControllerModeFlags}\");\nConsole.WriteLine($\"MTU: {can0.MaximumTransmissionUnit}\");\n```\n\n### Supported Environments\nThorough testing has been done for x64, ARM32 and ARM64 on Linux. Support for Raw CAN, Broadcast Manager, and CAN Gateway have been confirmed as far back as Linux Kernel 4.9. Support for Alpine Linux has been verified.\n\nSocketCAN# releases prior to 0.7.0 target .NET 5. SocketCAN# v0.7.0 and later target .NET Standard 2.0.\n\nSocketCAN# has been tested to run on Windows via the WSL (Windows Subsystem for Linux). Instructions on how to set up a WSL instance for running SocketCAN# are available [here](doc/WSLSetup.md).\n\n### Example Code\n\n* CanBusSniffer : Simple CAN bus analyzer.\n* IsoTpCommSimulator : ISO-TP communication simulation.\n* ObjectOrientedDiagAppSimulator : Diagnostic Application Simulator using IsoTpCanSocket objects.\n* J1939EngineSpeedTransmit : Simple application that sends the J1939 Engine Speed signal a couple of different ways using SocketCAN#.\n* CanNetlinkReader : Simple application that reads out CAN interface information using Netlink through various options offered by the SocketCAN# library.\n* J1939Sniffer : Basic J1939 bus sniffer utility to illustrate how to use SocketCAN# to monitor a J1939 network.\n* CanGatewayConfigTool : Sample application which adds a CAN GW rule, tests it, and then clears all CAN GW rules.\n* CanNetlinkConfigTool : Example application which modifies and displays CAN interface information using Netlink through various options offered by SocketCAN#.\n\n\n### Additional Information:\n\n* [License](LICENSE.md)\n* [Documentation](doc/Home.md)\n* [Comparison with Iot.Device.SocketCan](doc/IotDeviceSocketCanComparison.md)\n","funding_links":[],"categories":["C# #"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderek-will%2FSocketCANSharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fderek-will%2FSocketCANSharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderek-will%2FSocketCANSharp/lists"}