Het is trouwens verstandig om zowiezo aan beide kanten van je socket als eerste je output aan te maken, te flushen en dan je input.
Zo weet je dat zeker dat je socket nooit in een toestand komt dat er door de input stream op de flush van de andere kant staat te wachten..
Trouwens wat code die vast intressant voor je zal zijn:
De server:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
| /*
* Server.java
*
* Created on 22 januari 2001, 10:39
*/
package smartagenda.server;
import java.net.*;
import java.io.*;
import java.util.*;
import smartagenda.server.*;
import smartagenda.shared.*;
import smartagenda.shared.exceptions.*;
/**
*
* @author leenarts
* @version
*/
public class SmartagendaServer extends Object {
public final static int DEFAULT_PORT = 34567;
private ServerParameters config;
private SystemMessages messages = null;
protected AppointmentManager manager;
private ServerSocket server;
private Integer threadCounter = new Integer(0);
public SmartagendaServer(int port) throws IOException, BindException {
messages = new SystemMessages();
//messages.redirectOutput();
Date testDate = new Date();
messages.message("TEST: started on: " + testDate.toString());
config = new ServerParameters(messages);
/*if (config.getServerDebugMode() != messages.getDebugMode() )
{
messages.switchDebugMode();
}*/
manager = new AppointmentManager(config, messages);
messages.debugMessage("TEST: AppointmentManager created....");
server = new ServerSocket(port);
}
public void shutdown()
{
manager.shutdown();
messages.debugMessage("TEST: AppointmentManager shutdown....");
messages.debugMessage("TEST: shutting down messages");
Date testDate = new Date();
messages.message("TEST: ended on: " + testDate.toString());
messages.shutdown();
}
public void listenForClients(){
while(true) {
System.out.println("Server is running");
try {
Socket s = server.accept();
System.out.println("Client request received");
ClientThread t = new ClientThread(s, this);
t.start();
increaseThreadCounter();
printThreadCount();
}
catch (IOException e){
System.out.println("Thread creation failed because of IOException");
}
}
}
/**
* @param args the command line arguments
*/
public static void main (String args[]) {
int port = DEFAULT_PORT;
SmartagendaServer server;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
if (port < 0 || port >= 65536) {
System.out.println("Port number must be between 0 and 65535");
return;
}
}
catch (NumberFormatException e) {
//use default port
System.out.println("Illegal port number, using default port: 34567");
}
}
try {
server = new SmartagendaServer(port);
server.listenForClients();
}
catch (BindException e) {
System.err.println("Could not start server. Port Occupied!");
System.exit(-1);
}
catch(IOException e) {
System.err.println(e);
System.exit(-1);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void increaseThreadCounter()
{
synchronized (threadCounter)
{
int count = threadCounter.intValue();
count++;
threadCounter = new Integer(count);
}
}
public void decreaseThreadCounter()
{
synchronized (threadCounter)
{
int count = threadCounter.intValue();
count--;
threadCounter = new Integer(count);
}
}
public void printThreadCount()
{
synchronized (threadCounter)
{
messages.debugMessage("There are currently " + threadCounter.intValue() + " Client Threads running.");
}
}
} |
De thread voor iedere client op de server. Deze wordt aangemaakt door de bovenstaande klasse, vlak bij de accept methode.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
| /*
* ServerThread.java
*
* Created on 22 januari 2001, 11:08
*/
package smartagenda.server;
import java.net.*;
import java.io.*;
import smartagenda.shared.*;
import smartagenda.shared.exceptions.*;
/**
*
* @author leenarts
* @version
*/
public class ClientThread extends Thread {
private Socket sock;
private InetAddress adres;
private ObjectInputStream in;
private ObjectOutputStream out;
private SmartagendaServer server;
private final String modifierID;
/** Creates new ServerThread */
public ClientThread(Socket s, SmartagendaServer srvr) throws IOException {
this.sock = s;
this.server = srvr;
this.adres = sock.getInetAddress();
this.modifierID = adres.toString() + ":" + sock.getPort();
System.out.println(adres.toString());
System.out.println("initializing output");
this.out = new ObjectOutputStream(sock.getOutputStream());
this.out.flush();
System.out.println("initializing input");
this.in = new ObjectInputStream(sock.getInputStream());
System.out.println("input/output initialized");
}
public void run() {
System.out.println("Client Thread is running");
try {
while (this.sock != null) {
try {
int message = in.readInt();
process(message);
System.out.println("message processed");
}
catch (Exception e) {
System.out.println("Connection closed by client");
e.toString();
if (sock != null){
try {
this.sock.close();
this.sock = null;
}
catch (IOException ioex){}
}
}
}
}
finally
{
server.manager.dropModifiersAppointments(modifierID);
server.decreaseThreadCounter();
server.printThreadCount();
}
}
private void process(int message) {
TimeSlot timeslot = null;
Appointment appointment = null;
try {
System.out.println("about to enter switch");
switch ( message ) {
case Protocol.REQUEST:
timeslot = (TimeSlot) in.readObject();
try {
// request appointments
appointment = server.manager.requestAppointment(timeslot, this.modifierID );
out.writeInt(Protocol.REQUEST_RESPONSE);
out.writeObject(appointment);
}
catch(AppointmentCreationException ace)
{
System.out.println("TimeSlot for " + this.modifierID + " not allowed by manager.");
out.writeInt(Protocol.NO_SLOT_OPEN_ERROR);
out.writeObject(ace);
}
out.flush();
break;
/* case Protocol.SIMILAR:
timeslot = (TimeSlot) in.readObject();
//do something
break;
*/
case Protocol.STORE:
appointment = (Appointment) in.readObject();
try {
//store the appointment
server.manager.storeAppointment(appointment);
System.out.println("in clientthread: appointment stored");
out.writeInt(Protocol.STORE_RESPONSE);
System.out.println("in clientthread: protocol written");
}
catch (AppointmentNotAllowedException anae)
{
out.writeInt(Protocol.STORE_NOT_ALLOWED_EXCEPTION);
System.out.println("in clientthread: exception protocol written");
out.writeObject(anae);
System.out.println("in clientthread: exception object written");
}
out.flush();
System.out.println("in clientthread: output flushed");
break;
case Protocol.DROPALL:
//No Object to read, just drop all slots from memory
server.manager.dropModifiersAppointments(modifierID);
out.writeInt(Protocol.DROPALL_RESPONSE);
out.flush();
break;
/* case Protocol.DELETE:
timeslot = (TimeSlot) in.readObject();
//do something
break;
*/
case Protocol.GET_ACTIVE_CAMPAIGNS_ID:
//No object to read, just get all active campaigns and return
out.writeInt(Protocol.GET_ACTIVE_CAMPAIGNS_ID_RESPONSE);
out.writeObject(server.manager.getActiveCampaigns());
out.flush();
break;
default:
out.writeInt(Protocol.UNKNOWN);
out.flush();
}
}
catch(ClassNotFoundException cnfe)
{
try{
out.writeInt(Protocol.SERVER_ERROR);
out.flush();
if (sock != null){
try {
this.sock.close();
}
catch (IOException ioex){}
finally {
this.sock = null;
}
}
}
catch (Exception e) {}
}
catch(IOException ioe){
try{
out.writeInt(Protocol.SERVER_ERROR);
out.flush();
if (sock != null){
try {
this.sock.close();
this.sock = null;
}
catch (IOException ioex){}
finally {
this.sock = null;
}
}
}
catch (Exception e) {}
}
finally
{
appointment = null;
timeslot = null;
}
}
} |
En dit is de client die de verbinding legt met de server. Leuk detail, dit object was een object die als
Sessie variabele werd opgeslagen in een JSP pagina structuur. Dus voor iedere actieve sessie liep er een eigen thread op de server.
Hierdoor kreeg je deze structuur:
Webbrowser-webserver-mijn server met actieve thread per sessie-databaseserver.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
| package smartagenda.client.jspclient;
import java.net.*;
import java.io.*;
import java.util.*;
import smartagenda.shared.*;
import smartagenda.shared.exceptions.*;
public class JspSmartAgendaConnection {
public final static int DEFAULT_PORT = 34567;
public final static String DEFAULT_HOST = "localhost";
private Socket sock;
private ObjectOutputStream out;
private ObjectInputStream in;
public JspSmartAgendaConnection() throws IOException
{
int port = JspSmartAgendaConnection.DEFAULT_PORT;
InetAddress host = InetAddress.getByName(
JspSmartAgendaConnection.DEFAULT_HOST);
sock = new Socket(host, port);
out = new ObjectOutputStream(
new BufferedOutputStream(
sock.getOutputStream()
)
);
out.flush();
in = new ObjectInputStream(
new BufferedInputStream(
sock.getInputStream()
)
);
}
public Vector getPlannableCampaigns()
throws IOException,
ClassNotFoundException,
InternalServerException
{
Request request = new Request(Protocol.GET_ACTIVE_CAMPAIGNS_ID, null);
Response response = talkToServer(request);
checkForUnexpectedResponse(response);
return (Vector)response.responseObject;
}
public Appointment requestAppointment(TimeSlot timeslot)
throws IOException,
ClassNotFoundException,
AppointmentCreationException,
InternalServerException
{
Request request = new Request(Protocol.REQUEST, timeslot);
Response response = talkToServer(request);
checkForUnexpectedResponse(response);
if (response.responseProtocol == Protocol.NO_SLOT_OPEN_ERROR)
{
throw (AppointmentCreationException)response.responseObject;
}
return (Appointment)response.responseObject;
}
/* public Vector requestSimilarAppointment(TimeSlot timeslot)
throws IOException, ClassNotFoundException
{
Vector similarAppointments = null;
//do something
//make request
//process response
return similarAppointments;
}
*/
public void storeAppointment(Appointment appointment)
throws IOException,
ClassNotFoundException,
AppointmentNotAllowedException,
InternalServerException
{
System.out.println("in storeAppointment: 1");
Request request = new Request(Protocol.STORE, appointment);
System.out.println("in storeAppointment: 2");
Response response = talkToServer(request);
System.out.println("in storeAppointment: 3");
checkForUnexpectedResponse(response);
System.out.println("in storeAppointment: 4");
if (response.responseProtocol == Protocol.STORE_NOT_ALLOWED_EXCEPTION)
{
System.out.println("in storeAppointment: 5");
throw (AppointmentNotAllowedException)response.responseObject;
}
System.out.println("in storeAppointment: 6");
}
public void dropAll()
throws IOException,
ClassNotFoundException,
InternalServerException
{
Request request = new Request(Protocol.DROPALL, null);
Response response = talkToServer(request);
checkForUnexpectedResponse(response);
}
public void dropConnection()
{
out = null;
in = null;
try {
sock.close();
}
catch (IOException ioex){}
finally {
sock = null;
}
}
public boolean isValid()
{
if (sock == null)
{
return false;
}
else
{
return true;
}
}
private Response talkToServer(Request request)
throws IOException, ClassNotFoundException
{
// Send the request...
System.out.println("in talkToServer");
out.writeInt(request.requestProtocol);
System.out.println("in talkToServer: protocol send");
if (request.requestProtocol == Protocol.DROPALL ||
request.requestProtocol == Protocol.GET_ACTIVE_CAMPAIGNS_ID)
{
// DROPALL does not send an object to server.
// So don't send anything.
System.out.println("in talkToServer: NO object send");
}
else
{
out.writeObject(request.requestObject);
System.out.println("in talkToServer: object send");
}
out.flush();
System.out.println("in talkToServer: buffers flushed");
// Receive the response...
Response response = new Response();
System.out.println("in talkToServer: new response");
response.responseProtocol = in.readInt();
System.out.println("in talkToServer: protocol read");
//See if response has an attached object.
if (response.responseProtocol == Protocol.UNKNOWN ||
response.responseProtocol == Protocol.SERVER_ERROR ||
response.responseProtocol == Protocol.STORE_RESPONSE ||
response.responseProtocol == Protocol.DROPALL_RESPONSE)
{
// No object to be read in the stream, make null just to be sure.
response.responseObject = null;
System.out.println("in talkToServer: NO object read");
}
else
{
// If this point is reached,
// then there is an object waiting to be read in the inputstream.
response.responseObject = in.readObject();
System.out.println("in talkToServer: object read");
}
return response;
}
public String getText()
{
return "bladibla";
}
private void checkForUnexpectedResponse(Response response)
throws InternalServerException
{
if (response.responseProtocol == Protocol.UNKNOWN)
{
throw new InternalServerException("Unknown response received from server");
}
if (response.responseProtocol == Protocol.SERVER_ERROR)
{
throw new InternalServerException("Server error response received from server");
}
}
private class Response extends java.lang.Object {
public int responseProtocol;
public Object responseObject;
}
private class Request extends java.lang.Object {
public Request(int reqProt, Object reqObj)
{
requestProtocol = reqProt;
requestObject = reqObj;
}
public final int requestProtocol;
public final Object requestObject;
}
} |
let ook op het gebruik van Buffered streams, het scheelde bij mij echt aanzienelijk!!