Blame view

JChatClient/src/client.cpp 3.37 KB
1
2
3
4
5
6
7
/** @file 
* \brief Fichero de implementación de un cliente
* \author Imanol Barba Sabariego
* \date 13/06/2013
*
* En este fichero se implementa un cliente para poder usar con el servidor creado, usando la clase Socket.
*/
8
#include "client.h"
9
10
11
12
13
14
15
16
17
18

using namespace std;

bool connected, finished;

//! Método para terminar el cliente
/*! Este método se usa para terminar el cliente immediatamente en el caso que el servidor cierre la conexión de forma inesperada, capturando
el signal SIGPIPE. */
void exitClient(int signal/*!<Parámetro que captura el signal recibido*/)
{
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
	if(signal == SIGPIPE)
	{
		cout << "Server connection terminated unexpectedly" << endl << "Exiting" << endl;
		exit(-1);
	}
}

void killThread(thread_args *t_arg)
{
	(t_arg->s)->Close();
	pthread_mutex_lock(t_arg->mutex);
	if(t_arg->s != 0)
	{
		delete t_arg->s;
		t_arg->s = 0;
	}
	if(t_arg != 0)
	{
		delete t_arg;
		t_arg = 0;
	}
	pthread_exit(NULL);
41
42
43
44
}

bool connect(Socket& s)
{
45
	string host, nick;
46
	int port;
47
	/*cout << "Hostname: ";
48
49
	cin >> host;
	cout << "Port: ";
50
51
52
	cin >> port;*/
	cout << "Nickname: ";
	cin >> nick;
53
	cin.ignore();
54
55
56
	host = "localhost";
	port = 3001;
57
58
59
60
61
	try
	{
		s.Connect(host,port);
		cout << "Connected" << endl;
		connected = true;
62
		s << nick;
63
64
65
66
67
68
69
	}
	catch(SocketException& e)
	{
		cout << e.description() << endl;
	}
}
70
void* sendThread(void* args)
71
{
72
73
74
	string send;
	struct thread_args *t_arg = (struct thread_args*)args;
	while(true)
75
	{
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
		cout << "> ";
		getline(cin,send);
		if(cin.eof())
		{
			send = "/disconnect";
		}
		try
		{
			*(t_arg->s) << send;
			if(send == "/disconnect" || send == "/exit")
			{
				break;
			}
		}
		catch(SocketException& e)
		{
			cout << e.description() << endl;
			cout << "Exiting" << endl;
			(t_arg->s)->Close();
        	exit(-1);
		}
97
	}
98
99
100
101
102
103
104
105
	killThread(t_arg);
}

void* recvThread(void* args)
{
	string recv;
	struct thread_args *t_arg = (struct thread_args*)args;
	while(true)
106
	{
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
		*(t_arg->s) >> recv;
		if(recv == "DISC_OK")
		{
			cout << "Disconnecting" << endl;
			(t_arg->s)->Close();
	    	connected = false;
	    	pthread_cond_signal(t_arg->condition);
	    	break;
		}
		else if(recv == "EXIT_OK")
		{
			cout << "Exiting" << endl;
			(t_arg->s)->Close();
			connected = false;
			finished = true;
			pthread_cond_signal(t_arg->condition);
			break;
		}
		else
		{
			cout << recv << endl;
		}
129
	}
130
	killThread(t_arg);
131
132
133
134
135
136
137
138
139
}

//! Método principal del cliente
/*! Este método inicializa el Socket, establece la conexión y realiza las acciones que se le hayan programado para comunicarse con el servidor.*/
int main()
{
	signal(SIGPIPE, exitClient);
	Socket s;
	connected = finished = false;
140
141
142
143
144
145
146
	pthread_mutex_t mutex;
	pthread_mutex_init(&mutex,0);
	pthread_cond_t condition;
	pthread_cond_init(&condition,0);
	thread_args *sArgs = new thread_args;
	thread_args *rArgs = new thread_args;
	pthread_t recv, send;
147
	s.Create();
148
	while (!finished)
149
150
	{
		connect(s);
151
152
153
154
155
156
157
158
159
160
161
162
		pthread_mutex_lock(&mutex);
		sArgs->mutex = &mutex;
		sArgs->condition = &condition;
		sArgs->s = &s;

		rArgs->mutex = &mutex;
		rArgs->condition = &condition;
		rArgs->s = &s;

		pthread_create(&send,NULL,sendThread,(void *)sArgs);
		pthread_create(&recv,NULL,recvThread,(void *)rArgs);
163
164
		while(connected)
		{
165
			pthread_cond_wait(&condition,&mutex);
166
		}
167
		pthread_mutex_unlock(&mutex);
168
	}
169
170
	pthread_cond_destroy(&condition);
	pthread_mutex_destroy(&mutex);
171
172
}
173
/* TODO
174
 *
175
 * disconnecting causes some real shit
176
177
178
 * list nicks
 * unicast message
 */