When establishing a webSocket connection, it starts off as an http connection with special webSocket headers. It then transitions from http to the webSocket protocol once both sides agree to make the switch. This means that in order to handle webSocket connections, you need a listening http server in nodejs.
You don't necessarily have to use Express for your web server when dealing with incoming webSocket connections. You can simply use the plain http module in nodejs or any other method that listens for incoming http connections. However, socket.io seamlessly integrates with Express, requiring just a single line of code to connect socket.io with Express and start listening for incoming webSocket connections.
Additionally, many users who utilize socket.io are also serving web pages alongside their webServer. Express is a popular and straightforward way to serve web pages using nodejs, so it's common for those using socket.io to also be utilizing Express.