I’ve written a file uploader designed to send a file of program code from a C# client to a Java server. The server requires a valid username and password to be submitted prior to accepting the file upload.
Independently both the security (username and password) and the file uploader work correctly. However when I attempt to combine the two the code freezes on the C# client after receiving a ‘true’ boolean response back from the server (indicating a correct username and password). The relevant code from the client and server is attached.
C# Client
public static string sendValidatedFile(string username, string password, string path) {
string inputString = "NotSent";
try {
TcpClient client = new TcpClient("127.0.0.1", 42000);
StreamReader input = new StreamReader(stream);
Stream securityStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(username + "_" + password + "_\n"));
byte[] bufferA = new byte[securityStream.Length];
securityStream.Read(bufferA, 0, bufferA.Length);
stream.Write(bufferA, 0, bufferA.Length);
stream.Flush();
inputString = input.ReadToEnd();
bool result = bool.Parse(inputString);
if (result) {
print("Login Accepted");
Stream fileStream = File.OpenRead(path);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
// This is where the code seems to lock up
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
inputString = input.ReadToEnd();
}
else {
inputString = "Invalid Username or Password";
}
input.Close();
stream.Close();
client.Close();
}
catch (SocketException e) {
print("Error" + e);
}
catch (IOException e) {
print("Error" + e);
}
return inputString;
}
Java Server
public void run() {
try {
// Get username and password
byte[] byteArrayJAR = new byte[filesize];
byte[] byteArraySecurity = new byte[filesize];
InputStream input = socket.getInputStream();
PrintWriter output = new PrintWriter(socket.getOutputStream());
int bytesSecurity = input.read(byteArraySecurity, 0, byteArraySecurity.length);
int currentByte1 = bytesSecurity;
if (input.available() > 0) {
do {
bytesSecurity = input.read(
byteArraySecurity,
currentByte1,
(byteArraySecurity.length - currentByte1));
if (bytesSecurity >= 0) {
currentByte1 += bytesSecurity;
}
}
while (bytesSecurity > -1);
}
String securityString = new String(byteArraySecurity).trim();
String[] authenticationString = securityString.split("_");
String username = authenticationString[0];
String password = authenticationString[1];
// Validate the username and password with a stored database
if (security.validateUser(username, password)) {
// Inforn the client their username and password were accepted
output.println(true);
output.flush();
// Get the program code file
int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length);
int currentByte = bytesRead;
if (input.available() > 0) {
do {
bytesRead = input.read(
byteArrayJAR,
currentByte,
(byteArrayJAR.length - currentByte));
if (bytesRead >= 0) {
currentByte += bytesRead;
}
}
while (bytesRead > -1);
}
// Inform the client that the code was received
output.println("Success");
output.flush();
}
else {
// Inform the client their username or password was incorrect
output.println(false);
output.flush();
}
// Disconnect from client
output.flush();
output.close();
input.close();
socket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
Can anybody see anything wrong with the above that could be causing my code to hang? There is definately be data for the C# client to transmit on both instances. Is there a reason why two byte arrays can’t be sent from the same Network Stream in C#?
I’d appreciate any help anybody can offer in getting the above code to work without hanging.
Regards,
Midavi.
You are using input.ReadToEnd() twice. A stream only has one end; I suspect the first of these is out of place, and should be replaced with more direct reading – or at best, a ReadLine().
If the conversation here depends on multiple messages between client and server, you might also want to check if nagle is enabled, as it could be that one of the messages is still buffered and has not actually been sent yet (Flush() does nothing on a network stream) – you may have to set NoDelay (or the equivalent) for the socket. The default behaviour is to buffer small messages to prevent flooding the network with lots of tiny packets.