Usually you'd defined the protocol before writing any code. Otherwise you wouldn't know how to wright your software.
Think about when does a communication partner send what to the other one. Think like vlad tried to illustrate at a telephone call.
If your client f.e. asks some simple kind of file server to append some data at the end of a file.
Think about message flow:
1. --> Client opens connection.
2. --> Client sends a file name.
3.1 <-- Server accepts file name.
3.2 <-- Server doesn't accept file name. It returns an error condition.
4. --> Client may have to ask for permission to append something to this file.
5.1 <-- Server prohibits: The server replies accordingly and closes the connection.
5.2 <-- On permission the server may ask for the number of bytes to be appended.
...
Think about errors:
F.e. if you have defined a protocol like indicated above, you may have to define what's happening if a client starts conversation with step 4.
Think about data representation:
1. If you use some kind of low level communication like streaming or datagrams you may have to define how to set message boundaries (streaming) or how to ensure message order (datagram).
2. You may also have to define some representation of your data types. One aspect may be the byte order of integer values. How do you represent real numbers, or strings, or structures, ...?
In object oriented world you'll have objects communicating by sending messages to each other. A message may be executed by the receivers method implementation which in turn may result into some other messages being send to any object. Here you may use some kind of remote object messaging as defined f.e. in CORBA. Then you no longer have to think about many aspects of your data representation and others...