Commit 77176d9b80331d81b356ba95c063e7dcfc724d54

Authored by Imanol-Mikel Barba Sabariego
1 parent 8d957e00

git-svn-id: svn://imanolbarba.net/PAD@27 c2ee353e-ed0d-4329-bf56-03aec153487f

JChatClient/bin/client
No preview for this file type
JChatClient/src/Socket.cpp
... ... @@ -6,11 +6,6 @@
6 6 * En este fichero se implementan los métodos de la clase Socket definidos en Socket.h
7 7 */
8 8 #include "Socket.h"
9   -#include "SocketException.h"
10   -#include <sstream>
11   -#include <strings.h>
12   -#include <cstdlib>
13   -#include <netinet/tcp.h>
14 9  
15 10 using namespace std;
16 11  
... ... @@ -149,8 +144,11 @@ const Socket&amp; Socket::operator &lt;&lt; ( const std::string&amp; text)
149 144 }
150 145 sstream << length;
151 146 string len = sstream.str();
152   - Send(len.c_str(), len.length()+1);
153   - Send(text.c_str(), text.length());
  147 + char* msg = new char[len.length() + text.length() + 1];
  148 + strcpy(msg,len.c_str());
  149 + strcpy(msg+len.length()+1,text.c_str());
  150 + Send(msg, text.length() + len.length() + 1);
  151 + delete[] msg;
154 152 return *this;
155 153 }
156 154  
... ...
JChatClient/src/client.cpp
... ... @@ -25,13 +25,6 @@ void exitClient(int signal/*!&lt;Parámetro que captura el signal recibido*/)
25 25  
26 26 void killThread(thread_args *t_arg)
27 27 {
28   - (t_arg->s)->Close();
29   - pthread_mutex_lock(t_arg->mutex);
30   - if(t_arg->s != 0)
31   - {
32   - delete t_arg->s;
33   - t_arg->s = 0;
34   - }
35 28 if(t_arg != 0)
36 29 {
37 30 delete t_arg;
... ... @@ -42,42 +35,69 @@ void killThread(thread_args *t_arg)
42 35  
43 36 bool connect(Socket& s)
44 37 {
45   - string host, nick;
  38 + string host, nick, response;
46 39 int port;
47 40 /*cout << "Hostname: ";
48   - cin >> host;
  41 + getline(cin,host);
49 42 cout << "Port: ";
50 43 cin >> port;*/
51 44 cout << "Nickname: ";
52   - cin >> nick;
53   - cin.ignore();
  45 + getline(cin,nick);
54 46 host = "localhost";
55 47 port = 3001;
56 48  
57 49 try
58 50 {
  51 + s.Create();
59 52 s.Connect(host,port);
60 53 cout << "Connected" << endl;
61 54 connected = true;
62 55 s << nick;
  56 + s >> response;
  57 + while(response == "CHATNICKINVALID")
  58 + {
  59 + cout << "Spaces not allowed in nicknames, please enter another nickname: ";
  60 + getline(cin,nick);
  61 + s << nick;
  62 + s >> response;
  63 + }
  64 + while(response == "CHATNICKEXIST")
  65 + {
  66 + cout << "Nickname in use, please enter another nickname: ";
  67 + getline(cin,nick);
  68 + s << nick;
  69 + s >> response;
  70 + }
  71 + while(response == "CHATFULL")
  72 + {
  73 + cout << "Chatroom is full, please wait..." << endl;
  74 + s >> response;
  75 + }
  76 + if(response != "CHATOK")
  77 + {
  78 + cout << "Error: " << response << endl;
  79 + return false;
  80 + }
63 81 }
64 82 catch(SocketException& e)
65 83 {
66 84 cout << e.description() << endl;
  85 + exit(-1);
67 86 }
  87 + return true;
68 88 }
69 89  
70 90 void* sendThread(void* args)
71 91 {
72 92 string send;
73 93 struct thread_args *t_arg = (struct thread_args*)args;
74   - while(true)
  94 + while(connected)
75 95 {
76 96 cout << "> ";
77 97 getline(cin,send);
78 98 if(cin.eof())
79 99 {
80   - send = "/disconnect";
  100 + send = "/exit";
81 101 }
82 102 try
83 103 {
... ... @@ -90,9 +110,6 @@ void* sendThread(void* args)
90 110 catch(SocketException& e)
91 111 {
92 112 cout << e.description() << endl;
93   - cout << "Exiting" << endl;
94   - (t_arg->s)->Close();
95   - exit(-1);
96 113 }
97 114 }
98 115 killThread(t_arg);
... ... @@ -104,11 +121,20 @@ void* recvThread(void* args)
104 121 struct thread_args *t_arg = (struct thread_args*)args;
105 122 while(true)
106 123 {
107   - *(t_arg->s) >> recv;
  124 + try
  125 + {
  126 + *(t_arg->s) >> recv;
  127 + }
  128 + catch(SocketException &e)
  129 + {
  130 + connected = false;
  131 + cout << e.description() << endl;
  132 + (t_arg->s)->Close();
  133 + break;
  134 + }
108 135 if(recv == "DISC_OK")
109 136 {
110 137 cout << "Disconnecting" << endl;
111   - (t_arg->s)->Close();
112 138 connected = false;
113 139 pthread_cond_signal(t_arg->condition);
114 140 break;
... ... @@ -116,7 +142,6 @@ void* recvThread(void* args)
116 142 else if(recv == "EXIT_OK")
117 143 {
118 144 cout << "Exiting" << endl;
119   - (t_arg->s)->Close();
120 145 connected = false;
121 146 finished = true;
122 147 pthread_cond_signal(t_arg->condition);
... ... @@ -144,10 +169,15 @@ int main()
144 169 thread_args *sArgs = new thread_args;
145 170 thread_args *rArgs = new thread_args;
146 171 pthread_t recv, send;
147   - s.Create();
  172 + pthread_attr_t attr;
  173 + pthread_attr_init(&attr);
  174 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
148 175 while (!finished)
149 176 {
150   - connect(s);
  177 + if(!connect(s))
  178 + {
  179 + exit(-1);
  180 + }
151 181 pthread_mutex_lock(&mutex);
152 182 sArgs->mutex = &mutex;
153 183 sArgs->condition = &condition;
... ... @@ -157,14 +187,17 @@ int main()
157 187 rArgs->condition = &condition;
158 188 rArgs->s = &s;
159 189  
160   - pthread_create(&send,NULL,sendThread,(void *)sArgs);
161   - pthread_create(&recv,NULL,recvThread,(void *)rArgs);
  190 + pthread_create(&send,&attr,sendThread,(void *)sArgs);
  191 + pthread_create(&recv,&attr,recvThread,(void *)rArgs);
162 192  
163 193 while(connected)
164 194 {
165 195 pthread_cond_wait(&condition,&mutex);
166 196 }
167 197 pthread_mutex_unlock(&mutex);
  198 + pthread_join(recv,NULL);
  199 + pthread_join(send,NULL);
  200 + s.Close();
168 201 }
169 202 pthread_cond_destroy(&condition);
170 203 pthread_mutex_destroy(&mutex);
... ... @@ -172,7 +205,5 @@ int main()
172 205  
173 206 /* TODO
174 207 *
175   - * disconnecting causes some real shit
176   - * list nicks
177   - * unicast message
  208 + * CTRL+C
178 209 */
179 210 \ No newline at end of file
... ...
JChatClient/src/include/Socket.h
... ... @@ -9,13 +9,17 @@
9 9 #define SOCKET_H_
10 10  
11 11 #include <iostream>
  12 +#include <sstream>
  13 +#include "SocketException.h"
12 14 #include <sys/socket.h>
  15 +#include <sys/types.h>
13 16 #include <netinet/in.h>
  17 +#include <netinet/tcp.h>
14 18 #include <arpa/inet.h>
15 19 #include <netdb.h>
16   -#include <string>
17   -#include <sys/types.h>
18 20 #include <unistd.h>
  21 +#include <cstdlib>
  22 +#include <cstring>
19 23  
20 24 using namespace std;
21 25  
... ...
JChatServer/bin/pad/prac2/ChatException.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/Connection.class
No preview for this file type
JChatServer/bin/pad/prac2/JChat$1.class 0 → 100644
No preview for this file type
JChatServer/bin/pad/prac2/MyServerSocket.class
No preview for this file type
JChatServer/bin/pad/prac2/MySocket.class
No preview for this file type
JChatServer/bin/pad/prac2/Server.class
No preview for this file type
JChatServer/src/pad/prac2/ChatException.java 0 → 100644
  1 +package pad.prac2;
  2 +
  3 +public class ChatException extends Exception
  4 +{
  5 +
  6 + /**
  7 + *
  8 + */
  9 + private static final long serialVersionUID = 2263415822589627234L;
  10 +
  11 + public ChatException()
  12 + {
  13 + super();
  14 + }
  15 +
  16 + public ChatException(String message)
  17 + {
  18 + super(message);
  19 + }
  20 +
  21 +}
... ...
JChatServer/src/pad/prac2/Connection.java
... ... @@ -15,11 +15,6 @@ public class Connection extends Thread
15 15 sleep = true;
16 16 }
17 17  
18   - public void sendMessage(String message) throws IOException
19   - {
20   - socket.sendMsg(message);
21   - }
22   -
23 18 public void awake()
24 19 {
25 20 synchronized(this)
... ... @@ -32,9 +27,12 @@ public class Connection extends Thread
32 27 public void finish()
33 28 {
34 29 kill = true;
35   - sleep = false;
  30 + if(sleep)
  31 + {
  32 + sleep = false;
  33 + notify();
  34 + }
36 35 socket.close();
37   - this.notify();
38 36 }
39 37  
40 38 public void setSock(MySocket s)
... ... @@ -42,6 +40,11 @@ public class Connection extends Thread
42 40 socket = s;
43 41 }
44 42  
  43 + public void sendMessage(String message) throws IOException
  44 + {
  45 + socket.sendMsg(message);
  46 + }
  47 +
45 48 public void run()
46 49 {
47 50 while(!kill)
... ... @@ -60,45 +63,88 @@ public class Connection extends Thread
60 63 e.printStackTrace();
61 64 }
62 65 }
63   - String str = socket.recvMsg();
64   - serv.addToChatroom(this, str);
65 66 if(!kill)
66 67 {
67   - while(true)
  68 + String str;
  69 + try
68 70 {
69 71 str = socket.recvMsg();
70   - if(str != null)
  72 + while(str.contains(" "))
71 73 {
72   - try
  74 + socket.sendMsg("CHATNICKINVALID");
  75 + str = socket.recvMsg();
  76 + }
  77 + while(serv.isOnline(str))
  78 + {
  79 + socket.sendMsg("CHATNICKEXIST");
  80 + str = socket.recvMsg();
  81 + }
  82 + socket.sendMsg("CHATOK");
  83 + serv.addToChatroom(this, str);
  84 + }
  85 + catch (IOException e)
  86 + {
  87 + if(!kill)
  88 + {
  89 + System.out.println("TCP: Communication with client failed while entering chatroom");
  90 + sleep = true;
  91 + serv.finishWorker(this);
  92 + }
  93 + continue;
  94 + }
  95 + while(true)
  96 + {
  97 + try
  98 + {
  99 + str = "";
  100 + str = socket.recvMsg();
  101 + if(str.equals("/disconnect"))
73 102 {
74   - if(str.equals("/disconnect"))
75   - {
76   - socket.sendMsg("DISC_OK");
77   - kill = true;
78   - System.out.println(serv.getNickname(this) + " disconnected");
79   - break;
80   - }
81   - else if(str.equals("/exit"))
  103 + socket.sendMsg("DISC_OK");
  104 + System.out.println(serv.getNickname(this) + " disconnected");
  105 + break;
  106 + }
  107 + else if(str.equals("/exit"))
  108 + {
  109 + socket.sendMsg("EXIT_OK");
  110 + System.out.println(serv.getNickname(this) + " disconnected");
  111 + break;
  112 + }
  113 + else if(str.equals("/who"))
  114 + {
  115 + socket.sendMsg(serv.listOnline());
  116 + }
  117 + else if(str.startsWith("@"))
  118 + {
  119 + try
82 120 {
83   - socket.sendMsg("EXIT_OK");
84   - kill = true;
85   - System.out.println(serv.getNickname(this) + " disconnected");
86   - break;
  121 + if(!str.contains(" "))
  122 + {
  123 + serv.sendTo(this,str.substring(1),"");
  124 + }
  125 + else
  126 + {
  127 + serv.sendTo(this,str.substring(1,str.indexOf(' ')),str.substring(str.indexOf(' ')+1));
  128 + }
87 129 }
88   - else
  130 + catch(ChatException cE)
89 131 {
90   - System.out.println("FROM " + serv.getNickname(this) + ": " + str);
91   - serv.sendToChat(this,str);
  132 + socket.sendMsg(cE.getMessage());
92 133 }
93 134 }
94   - catch(IOException ioExc)
  135 + else if(str.equals(""))
95 136 {
96   - System.out.println("TCP: Error writing to socket");
97 137 break;
98 138 }
  139 + else
  140 + {
  141 + System.out.println("FROM " + serv.getNickname(this) + ": " + str);
  142 + serv.sendToChat(this,str);
  143 + }
99 144 }
100   - else
  145 + catch(IOException ioExc)
101 146 {
  147 + System.out.println("TCP: Error writing to socket");
102 148 break;
103 149 }
104 150 }
... ... @@ -107,5 +153,4 @@ public class Connection extends Thread
107 153 serv.finishWorker(this);
108 154 }
109 155 }
110   -
111 156 }
... ...
JChatServer/src/pad/prac2/JChat.java
... ... @@ -25,7 +25,7 @@ public class JChat
25 25 {
26 26 public void run()
27 27 {
28   - System.out.println("JChat: interrupt catched, killing server...");
  28 + System.out.println("JChat: Caught interrupt, killing server...");
29 29 serv.killServer();
30 30 }
31 31 });
... ... @@ -34,8 +34,6 @@ public class JChat
34 34 /*
35 35 * TODO
36 36 *
37   - * unicast message
38   - * list nicks
39   - * disconnect/reconnect successfully
  37 + * CTRL+C
40 38 */
41 39 }
... ...
JChatServer/src/pad/prac2/MyServerSocket.java
... ... @@ -12,22 +12,6 @@ public class MyServerSocket extends ServerSocket
12 12 super();
13 13 }
14 14  
15   - public MySocket accept()
16   - {
17   - try
18   - {
19   - MySocket incoming = new MySocket();
20   - super.implAccept(incoming);
21   - incoming.initializeStreams();
22   - return incoming;
23   - }
24   - catch(IOException ioExc)
25   - {
26   - System.out.println("TCP: Error accepting connection");
27   - return null;
28   - }
29   - }
30   -
31 15 public void bind(String ip, int port)
32 16 {
33 17 SocketAddress addr = new InetSocketAddress(ip,port);
... ... @@ -41,6 +25,14 @@ public class MyServerSocket extends ServerSocket
41 25 }
42 26 }
43 27  
  28 + public MySocket accept() throws IOException
  29 + {
  30 + MySocket incoming = new MySocket();
  31 + super.implAccept(incoming);
  32 + incoming.initializeStreams();
  33 + return incoming;
  34 + }
  35 +
44 36 public void close()
45 37 {
46 38 try
... ...
JChatServer/src/pad/prac2/MySocket.java
... ... @@ -45,28 +45,13 @@ public class MySocket extends Socket
45 45 }
46 46 }
47 47  
48   - public void close()
49   - {
50   - try
51   - {
52   - super.shutdownInput();
53   - super.shutdownOutput();
54   - super.close();
55   - }
56   - catch(IOException ioExc)
57   - {
58   - System.out.println("TCP: Error while closing socket");
59   - }
60   - }
61   -
62 48 public void sendMsg(String msg) throws IOException
63 49 {
64 50 String length = new Integer(msg.length()).toString();
65   - this.write(length + '\0');
66   - this.write(msg);
  51 + this.write(length + '\0' + msg);
67 52 }
68 53  
69   - public String recvMsg()
  54 + public String recvMsg() throws IOException
70 55 {
71 56 String len,str;
72 57 int length;
... ... @@ -100,28 +85,34 @@ public class MySocket extends Socket
100 85 }
101 86 }
102 87  
103   - public String readLine()
  88 + public String readLine() throws IOException
104 89 {
105   - try
  90 +
  91 + String line = "";
  92 + char[] c = new char[1];
  93 + while(true)
106 94 {
107   - String line = "";
108   - char[] c = new char[1];
109   - while(true)
  95 + input.read(c,0,1);
  96 + if(c[0] == '\0')
110 97 {
111   - input.read(c,0,1);
112   - if(c[0] == '\0')
113   - {
114   - break;
115   - }
116   - line += c[0];
  98 + break;
117 99 }
118   - return line;
  100 + line += c[0];
  101 + }
  102 + return line;
  103 + }
  104 +
  105 + public void close()
  106 + {
  107 + try
  108 + {
  109 + super.shutdownInput();
  110 + super.shutdownOutput();
  111 + super.close();
119 112 }
120 113 catch(IOException ioExc)
121 114 {
122   - System.out.println("TCP: Error retrieving data from remote endpoint");
123   - return null;
  115 + System.out.println("TCP: Error while closing socket");
124 116 }
125 117 }
126   -
127 118 }
128 119 \ No newline at end of file
... ...
JChatServer/src/pad/prac2/Server.java
1 1 package pad.prac2;
2 2  
3 3 import java.io.IOException;
  4 +import java.util.Collection;
4 5 import java.util.Iterator;
5 6 import java.util.Set;
6 7 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -44,35 +45,24 @@ public class Server
44 45 }
45 46 }
46 47  
47   - public void sendToChat(Connection origin, String message) throws IOException
48   - {
49   - lock.lock();
50   - String nickname = activeConnections.get(origin);
51   - Set<Connection> connections = activeConnections.keySet();
52   - Iterator<Connection> it = connections.iterator();
53   - Connection conn;
54   - while(it.hasNext())
55   - {
56   - conn = it.next();
57   - if(conn != origin)
58   - {
59   - conn.sendMessage(nickname + ": " + message);
60   - }
61   - }
62   - lock.unlock();
63   - }
64   -
65 48 public void startServer()
66 49 {
67 50 while(!kill)
68 51 {
69   - MySocket incoming = ss.accept();
70   - if(incoming != null)
  52 + try
71 53 {
  54 + MySocket incoming = ss.accept();
72 55 System.out.println("Accepted connection from " + incoming.getInetAddress());
73   -
74 56 startWorker(incoming);
75 57 }
  58 + catch(IOException ioExc)
  59 + {
  60 + if(!kill)
  61 + {
  62 + System.out.println("TCP: Error accepting connection");
  63 + break;
  64 + }
  65 + }
76 66 }
77 67  
78 68 }
... ... @@ -84,14 +74,20 @@ public class Server
84 74 {
85 75 try
86 76 {
87   - lock.unlock();
88   - availableWorkers.await();
89   - lock.lock();
  77 + s.sendMsg("CHATFULL");
  78 + synchronized(this)
  79 + {
  80 + availableWorkers.await();
  81 + }
90 82 }
91 83 catch(InterruptedException intExc)
92 84 {
93 85 intExc.printStackTrace();
94 86 }
  87 + catch(IOException ioExc)
  88 + {
  89 + System.out.println("TCP: Error while sending message to client");
  90 + }
95 91 }
96 92 workerPool[roomSize - freeWorkers].setSock(s);
97 93 workerPool[roomSize - freeWorkers].awake();
... ... @@ -100,34 +96,91 @@ public class Server
100 96 lock.unlock();
101 97 }
102 98  
103   - public String getNickname(Connection c)
104   - {
105   - return activeConnections.get(c);
106   - }
107   -
108 99 public void finishWorker(Connection c)
109 100 {
110 101 lock.lock();
  102 + removeFromChatroom(c);
111 103 freeWorkers++;
112 104 workerPool[roomSize - freeWorkers] = c;
113 105 availableWorkers.signal();
114 106 lock.unlock();
115 107 }
116 108  
  109 + public void sendTo(Connection orig, String nick, String msg) throws IOException, ChatException
  110 + {
  111 + lock.lock();
  112 + System.out.println("FROM " + getNickname(orig) + " TO " + nick + ": " + msg);
  113 + msg = getNickname(orig) + ": " + msg;
  114 + Set<Connection> conns = activeConnections.keySet();
  115 + Iterator<Connection> it = conns.iterator();
  116 + Connection dest;
  117 + while(it.hasNext())
  118 + {
  119 + dest = it.next();
  120 + if(getNickname(dest).equals(nick))
  121 + {
  122 + dest.sendMessage(msg);
  123 + lock.unlock();
  124 + return;
  125 + }
  126 + }
  127 + lock.unlock();
  128 + throw new ChatException("No such nickname");
  129 + }
  130 +
  131 + public void sendToChat(Connection origin, String message) throws IOException
  132 + {
  133 + lock.lock();
  134 + String nickname = activeConnections.get(origin);
  135 + Set<Connection> connections = activeConnections.keySet();
  136 + Iterator<Connection> it = connections.iterator();
  137 + Connection conn;
  138 + while(it.hasNext())
  139 + {
  140 + conn = it.next();
  141 + if(conn != origin)
  142 + {
  143 + conn.sendMessage(nickname + ": " + message);
  144 + }
  145 + }
  146 + lock.unlock();
  147 + }
  148 +
  149 + public String getNickname(Connection c)
  150 + {
  151 + return activeConnections.get(c);
  152 + }
  153 +
117 154 public void addToChatroom(Connection c, String nickName)
118 155 {
119 156 activeConnections.put(c, nickName);
120 157 System.out.println(nickName + " has entered the room");
121 158 }
122 159  
123   - public void finishConnections()
  160 + private void removeFromChatroom(Connection c)
124 161 {
125   - Set<Connection> conns = activeConnections.keySet();
126   - Iterator<Connection> it = conns.iterator();
  162 + activeConnections.remove(c);
  163 + }
  164 +
  165 + public boolean isOnline(String nick)
  166 + {
  167 + return activeConnections.contains(nick);
  168 + }
  169 +
  170 + public String listOnline()
  171 + {
  172 + lock.lock();
  173 + String ret = new Integer(activeConnections.size()).toString();
  174 + ret += " people currently online:";
  175 + Collection<String> nickNames = activeConnections.values();
  176 + Iterator<String> it = nickNames.iterator();
127 177 while(it.hasNext())
128 178 {
129   - it.next().finish();
  179 + ret += "\n";
  180 + ret += it.next();
130 181 }
  182 + lock.unlock();
  183 + return ret;
131 184 }
132 185  
133 186 public void killServer()
... ... @@ -136,4 +189,14 @@ public class Server
136 189 ss.close();
137 190 finishConnections();
138 191 }
  192 +
  193 + public void finishConnections()
  194 + {
  195 + Set<Connection> conns = activeConnections.keySet();
  196 + Iterator<Connection> it = conns.iterator();
  197 + while(it.hasNext())
  198 + {
  199 + it.next().finish();
  200 + }
  201 + }
139 202 }
... ...