A cookie is a small piece of text that is sent by the server to the client in the HTTP response headers. The client will store it locally and return it back to the server with every request in the request headers. That allows the implementation of some state in the otherwise stateless HTTP protocol.
A session is a concept typically implemented on top of cookies. The server sends a meaningless, unique session token (a random id) as a cookie to the client and the client returns it on every request. Server-side this id is associated with some data. Every time a client sends its session token back to the server in a request, the server looks up the data associated with that token.
The transfer of the session id back and forth between the client and the server can also happen by embedding the session id into all URLs or form requests, it doesn't have to be cookies. Embedding session ids in the URL is a bad idea though, since that allows accidental session transfers if URLs are shared between different users (see below). These days sessions are typically implemented using cookies client-side.
Conceptually cookies and sessions are extremely similar, they both implement state in HTTP. The difference is that a cookie can only store a small amount of data which is transferred back and forth on every request and is editable by the user (because it's information stored on the client); while a session stores all data server-side and is thereby only limited by the server's resources. The only vulnerability sessions have is that if a user can guess or steal the session id of another user, he can impersonate that user. That's known as session hijacking. Plain cookies have no security whatsoever and should not be used for anything important (as in, the user can see and edit the contents, so storing userloggedin=yes
in a cookie is the worst thing you can do).