diff --git a/Makefile b/Makefile
index b76d9812bd4615d9d6eea2e56b60bb0da1ae0947..a2a739a296e3a295ac46b79f11d491082b5ec9f1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,15 @@
-CFLAGS= -g -Wall -O2
+CFLAGS= -w -g -Wall -O2
 CC=g++
 
-OBJ=Protocol.o
+OBJ=Protocol.o Message.o
+
+all: cacoclient cacoserver
 
 %.o: %.cpp
 	$(CC) $(CFLAGS) $^ -c -o $@
 cacoclient: client.cpp $(OBJ)
 	$(CC) $(CFLAGS) $^ -o $@
-# cacoserver: $(OBJ) client.cpp
-# 	$(CC) $(CFLAGS) $^ -o $@
+cacoserver: server.cpp $(OBJ)
+	$(CC) $(CFLAGS) $^ -o $@
 clean:
 	rm -f *.o caco*
diff --git a/Message.cpp b/Message.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ca83b764cb679e6f5b6b641abf1e8bfdf2a64760
--- /dev/null
+++ b/Message.cpp
@@ -0,0 +1,28 @@
+#include "Message.h"
+#include "definitions.h"
+
+BYTE Message::calcParity() {
+    char parity = 0x00;
+    char *m = this->header.c_ctrl.begin + this->header.c_ctrl.sizeSeq + this->header.c_ctrl.seqType + (char *)(&data[0]);
+    for(int i=0; i < strlen(m); ++i) {
+        parity = parity^m[i];
+    }
+    this->header.c_ctrl.parity = parity;
+    return parity;
+}
+
+bool Message::checkParity() {
+    BYTE parity = this->calcParity();
+    return (parity == this->header.c_ctrl.parity);
+}
+
+string Message::getSendData() {
+    calcParity();
+    string s(data.begin(), data.end());
+    string d = header.c_ctrl.begin + header.c_ctrl.sizeSeq + header.c_ctrl.seqType + s.c_str() + header.c_ctrl.parity;
+    return d;
+}
+
+Message::Message() {
+    this->header.c_ctrl.begin = BEGIN;
+}
diff --git a/Message.h b/Message.h
new file mode 100644
index 0000000000000000000000000000000000000000..071f1956829095c0fc3a72bef1c21ae6db2494c4
--- /dev/null
+++ b/Message.h
@@ -0,0 +1,16 @@
+#ifndef __MESSAGE__
+#define __MESSAGE__
+#include "definitions.h"
+
+class Message {
+
+public:
+    Header header;
+    vector<BYTE> data;
+    BYTE calcParity();
+    bool checkParity();
+    string getSendData();
+
+    Message();
+};
+#endif
diff --git a/Protocol.cpp b/Protocol.cpp
index cb2fd145f95bcff4fc484fd878beec25b6df6d96..4ad3707ab0a96cb4334ec810eceb66dcf96ea6f8 100644
--- a/Protocol.cpp
+++ b/Protocol.cpp
@@ -1,33 +1,112 @@
+#include <sys/socket.h>
 #include "Protocol.h"
 #include "definitions.h"
 
-Message Protocol::getMessage(){
-    return message;
+vector<Message> Protocol::getMessages(){
+    return messages;
 }
 
-void Protocol::setMessage(Message message){
-    this->message = message;
+void Protocol::setMessages(vector<Message> messages){
+    this->messages = messages;
 }
 
-bool Protocol::send(int socket) {
+bool Protocol::send(int socket, int window) {
+    for(int i=0; i < messages.size(); ++i) {
+        string data = messages[i].getSendData();
+    }
     return true;
 }
 
-char Protocol::calcParity() {
-    char parity = 0x00;
-    char *m = this->message.c_ctrl.begin + this->message.c_ctrl.size + this->message.c_ctrl.seqType + (&data[0]);
-    for(int i=0; i < strlen(m); ++i) {
-        parity = parity^m[i];
+vector<BYTE> Protocol::getData(){
+    vector<BYTE> fullData;
+    for (int i=0; i < messages.size(); ++i){
+        fullData.insert(fullData.end(), messages[i].data.begin(), messages[i].data.end());
+    }
+    return fullData;
+}
+
+string Protocol::getDataAsString(){
+    vector<BYTE> fullData = getData();
+    string str(fullData.begin(), fullData.end());
+    return str;
+}
+
+void Protocol::setData(vector<BYTE> data, int type){
+    vector<BYTE>::const_iterator first, last;
+    int i;
+    for (i=0; i <= data.size()-MAXSIZE; i+=MAXSIZE){
+        Message msg;
+        msg.header.i_ctrl.begin = BEGIN;
+        msg.header.i_ctrl.size = MAXSIZE;
+        msg.header.i_ctrl.sequence = messages.size()%(MAXSIZE+1);
+        msg.header.i_ctrl.type = type;
+        first = data.begin()+i;
+        last = data.begin()+i+MAXSIZE+1;
+        vector<BYTE> subvector(first, last);
+        msg.data = subvector;
+        //TODO: Set parity
+        messages.push_back(msg);
+    }
+    if(i < data.size()){
+        Message msg;
+        msg.header.i_ctrl.begin = BEGIN;
+        msg.header.i_ctrl.sequence = messages.size()%(MAXSIZE+1);
+        msg.header.i_ctrl.type = type;
+        int size = data.size()-i;
+        first = data.begin()+i;
+        last = data.begin()+size+1;
+        vector<BYTE> subvector(first, last);
+        msg.data = subvector;
+        if(size < MINSIZE){
+            size = MINSIZE;
+            msg.data.insert(msg.data.begin(), MINSIZE-size, 0x0);
+        }
+        msg.header.i_ctrl.size = size;
+        //TODO: Set parity
+        messages.push_back(msg);
+    }
+}
+
+int Protocol::recvMessage(int sockt){
+    BYTE dataRec[MAXSIZE+4];
+    recv(sockt, dataRec, MAXSIZE, 0);
+    Message msg;
+    msg.header.c_ctrl.begin = dataRec[0];
+    if(msg.header.i_ctrl.begin != BEGIN){
+        return NOISE;
+    }
+    msg.header.c_ctrl.sizeSeq = dataRec[1];
+    msg.header.c_ctrl.seqType = dataRec[2];
+    if(msg.header.i_ctrl.sequence != ((messages.back().header.i_ctrl.sequence+1)%(MAXSIZE+1))){
+        return SEQ_MISS;
     }
-    this->message.c_ctrl.parity = parity;
-    return parity;
+    msg.header.c_ctrl.parity = dataRec[3+msg.header.i_ctrl.size];
+    // TODO: Check parity
+    if(msg.header.i_ctrl.type == ENDTX){
+        return ENDTX;
+    }
+
+    BYTE msgData[msg.header.i_ctrl.size];
+    memcpy(msgData,dataRec+3,msg.header.i_ctrl.size);
+    msg.data.insert(msg.data.end(), msgData, msgData+msg.header.i_ctrl.size);
+    messages.push_back(msg);
+    return msg.header.i_ctrl.type;
 }
 
-bool Protocol::checkParity() {
-    char parity = this->calcParity();
-    return (parity == this->message.c_ctrl.parity);
+// void Protocol::recvWholeData(int sockt, int window){
+//     int status;
+//     while((status=this->recvMessage(sockt)) != ENDTX){
+//         if(status > 0){
+//             if(messages.back().header.i_ctrl.sequence % window == 0){
+//                 //TODO: send ACK
+//             }
+//         }
+//     }
+// }
+
+void Protocol::addMessage(Message msg) {
+    messages.push_back(msg);
 }
 
 Protocol::Protocol(){
-    this->message.c_ctrl.begin = 0x7E;
 }
diff --git a/Protocol.h b/Protocol.h
index adcc99425e29dc545298746f5871a209636bdca0..040f6d9fb1cb33f97a7ba44bd33d69bfb8b157b1 100644
--- a/Protocol.h
+++ b/Protocol.h
@@ -1,19 +1,22 @@
 #ifndef __PROTOCOL__
 #define __PROTOCOL__
 #include "definitions.h"
+#include "Message.h"
 
 class Protocol{
 
 private:
-    Message message;
-    vector<char> data;
+    vector<Message> messages;
+    int timeout;
 public:
-
-    Message getMessage();
-    void setMessage(Message message);
-    bool send(int socket);
-    char calcParity();
-    bool checkParity();
+    bool send(int socket, int window);
+    vector<Message> getMessages();
+    void setMessages(vector<Message> messages);
+    vector<BYTE> getData();
+    void setData(vector<BYTE> data, int type);
+    string getDataAsString();
+    int recvMessage(int sockt);
+    void addMessage(Message msg);
 
     Protocol();
 };
diff --git a/client.cpp b/client.cpp
index febcc73f0af06f7951e6da9e6bce9af3bf26fc53..9d7a6e043569d721bd17cb1a9ee245dd79504b6c 100644
--- a/client.cpp
+++ b/client.cpp
@@ -1,32 +1,69 @@
+#include <stdexcept>
 #include "definitions.h"
 #include "dirFunctions.h"
 #include "ConexaoRawSocket.c"
+#include "Protocol.h"
 
-int main(){
+void printCommandsList();
 
-    int socket = ConexaoRawSocket(DEVICE);
-    
+int main(){
+    int pos, sockt = ConexaoRawSocket(DEVICE);
+    string line, command, args;
+    Protocol protocol = Protocol();
+    printCommandsList();
     while(true){
-        string command, path;
         cout << endl << "Entre com o comando:" << endl;
-        cin >> command;
-        if(command == "quit"){
-            break;
+        getline(cin,line);
+        pos = line.find_first_of(" ");
+        if(pos == string::npos){
+            pos = line.size();
         }
-        cin >> path;
-        if(command == "cd"){
-            cd(path);
-        }else if(command == "ls"){
-            ls(path);
-        }else if(command == "cdr"){
-            //TODO
-        }else if(command == "lsr"){
-            //TODO
-        }else if(command == "put"){
-            //TODO
-        }else if(command == "get"){
-            //TODO
+        command = line.substr(0,pos);
+        try{
+            if(command == "quit"){
+                break;
+            }
+            if(command == "cd"){
+                args = line.substr(pos+1, line.size());
+                cd(args);
+            }else if(command == "ls"){
+                cout << ls(line);
+            }else if(command == "cdr"){
+                //TODO
+            }else if(command == "lsr"){
+                Message msg = Message();
+                msg.header.i_ctrl.type = LS;
+                msg.data = vector<BYTE>(line.begin(), line.end());
+                protocol.addMessage(msg);
+                protocol.send(sockt, WAIT_STOP);
+                // TODO: imprimir resposta
+            }else if(command == "put"){
+                //TODO
+            }else if(command == "get"){
+
+            }else if(command == "help"){
+                printCommandsList();
+            }else{
+                cout << "Comando inexistente." << endl;
+                printCommandsList();
+            }
+        }catch(char const* strException){
+            cerr<<"Error: "<< strException << endl;
+        }catch(out_of_range e){
+            cerr<<"Error: Esse comando requer argumentos."<<endl;
         }
     }
     return 0;
-}
\ No newline at end of file
+}
+
+void printCommandsList(){
+    cout << "Os comandos suportados são:"<< endl;
+    cout << "cd - Mudar de diretório local"<< endl;
+    cout << "ls - Visualizar arquivos no diretório local"<< endl;
+    cout << "cdr - Mudar de diretório remoto"<< endl;
+    cout << "lsr - Visualizar arquivos no diretório remoto"<< endl;
+    cout << "put - Enviar arquivo para diretório remoto"<< endl;
+    cout << "get - Pegar arquivo do diretório remoto"<< endl;
+    cout << "help - Lista de comandos"<< endl;
+    cout << "quit - Sair"<< endl;
+}
diff --git a/definitions.h b/definitions.h
index 41172491abff370859092b839caa2404ced9e754..8269b16c18fc86321eaf8a3db16dbd77378880a5 100644
--- a/definitions.h
+++ b/definitions.h
@@ -7,7 +7,15 @@
 
 using namespace std;
 
+//Maximum and minimum of bytes in data field
+#define MAXSIZE 63
+#define MINSIZE 60
+
+//Delimiter indicating beginning of a message
+#define BEGIN 0x7E
+//Socket device
 #define DEVICE "lo"
+//Message types
 #define NACK 0
 #define ACK 1
 #define CD 3
@@ -15,10 +23,28 @@ using namespace std;
 #define PUT 5
 #define GET 6
 #define OK 8
-#define TAM 9
-#define TELA 10
-#define ERRO 14
-#define FIM 15
+#define SIZE 9
+#define OUTPUT 10
+#define DATA 13
+#define ERROR 14
+#define ENDTX 15
+
+//Windows
+#define WAIT_STOP 1
+#define SLIDING 3
+
+//Values of data for ERROR messages
+#define DIR_ERR '0'
+#define PERM_ERR '1'
+#define SPACE_ERR '2'
+
+//recvMessage errors
+#define NOISE -1
+#define SEQ_MISS -2
+#define INCONSISTENT -3
+
+//Data types
+#define BYTE unsigned char
 
 typedef struct{
 	int begin   : 8,
@@ -29,13 +55,12 @@ typedef struct{
 }i_Control;
 
 typedef struct{
-	char begin,size,seqType,parity;
+	char begin,sizeSeq,seqType,parity;
 }c_Control;
 
 typedef union {
 	c_Control c_ctrl;
     i_Control i_ctrl;
-}Message;
-
+}Header;
 
-#endif
\ No newline at end of file
+#endif
diff --git a/dirFunctions.cpp b/dirFunctions.cpp
index 078e39c86c8e4134e08d493d9a79043593ddaba9..bb8964a28e48d098d6051a59ce72882a376d9752 100644
--- a/dirFunctions.cpp
+++ b/dirFunctions.cpp
@@ -1,8 +1,9 @@
 #include <iostream>
 #include <errno.h>
 #include <unistd.h>
-#include <dirent.h>
 #include <string.h>
+#include <vector>
+#include <stdio.h> //popen
 
 using namespace std;
 
@@ -13,16 +14,16 @@ void cd(string path){
     }
 }
 
-void ls(string path){
-    //TODO: #1
-    struct dirent *entry;
-    DIR *dir = opendir(path.c_str());
-    if(dir != NULL){
-        while((entry=readdir(dir)) != NULL){
-           cout << entry->d_name << endl;
-        }
-        closedir(dir);
-    }else{
-        cout<<"Error: could not open directory."<<endl;
+string ls(string args){
+    string output;
+    FILE *lsOut = popen(args.c_str(), "r");
+    if(!lsOut){
+        throw "Couldn't execute ls";
     }
+    char buffer[1024];
+    while(fgets(buffer, sizeof(buffer), lsOut)!=NULL){
+        output += buffer;
+    }
+    pclose(lsOut);
+    return output;
 }
\ No newline at end of file
diff --git a/dirFunctions.h b/dirFunctions.h
index 1cb22424a70c1b679ffde53db571a39f89c614b8..fe120405bd8f732f027633b8b0ad3107c3d8b0a0 100644
--- a/dirFunctions.h
+++ b/dirFunctions.h
@@ -7,6 +7,6 @@ using namespace std;
 
 void cd(string path);
 
-void ls(string path);
+string ls(string path);
 
 #endif
\ No newline at end of file
diff --git a/server.cpp b/server.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a21d9460a73e5309a73276cbc9a625fce0b3f4e
--- /dev/null
+++ b/server.cpp
@@ -0,0 +1,28 @@
+#include "definitions.h"
+#include "Protocol.h"
+#include "dirFunctions.h"
+#include "ConexaoRawSocket.c"
+
+int main(){
+    int sockt = ConexaoRawSocket(DEVICE);
+    Protocol protocol;
+    while(true){
+        int status = protocol.recvMessage(sockt);
+        if(status > 0){
+            if(status == ENDTX){
+                protocol = Protocol();
+                //TODO: send ACK
+            }else if(status == CD){
+                cd(protocol.getDataAsString());
+            }else if(status == LS){
+                string output = ls(protocol.getDataAsString());
+                //TODO: send output back
+            }else if(status == PUT){
+                //TODO
+            }else if(status == GET){
+                //TODO
+            }
+        }
+    }
+    return 0;
+}
\ No newline at end of file