I have a client implemented in Java, and a server implemented in client.
The client sends a message (string) such as "nesting:1:2" to the server, the server decodes the meaning of the input to create and send back binary data to the client.
This is the Python server code.
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
# self.data has the data
(name, index, n) = self.data.split(":")
m = int(n)
i = int(index)
size = sizes.sizes[name][i]
# creates the binary data
bf = [0x41] * size * m
key = ''.join(chr(x) for x in bf)
self.request.send(key) #
if __name__ == "__main__":
HOST = socket.gethostbyname(socket.gethostname())
PORT = 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
The client Python code is as follows:
af, socktype, proto. canonname, sa = res
s = socket(af, socktype, proto)
s.connect(sa)
s.sendall('nostring:1:5')
data = s.recv(1024)
s.close()
I tried to find the equivalent to the s.recv() method, I found read() method. So, I tried this method where byte[] buffer = new byte[157*10]; is declared outside the method.
public byte[] receive() throws IOException {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVER_PORT);
in = socket.getInputStream();
in.read(buffer);
in.close();
socket.close();
return this.buffer;
}
The issue is that the in.read(buffer) never returns until the server disconnects.
What might be wrong? This is the full source code for the client.
I didn't try, but to my mind, the socket should not be closed between the send and receive action, one socket means one connection to the server.
The python server will most likely try to answer on the given socket, which will be closed, and the java client will wait on another.
Try something like that: creating the socket in the constructor and closing it at the end of the receive (if you are sure you might call the send/receive pair only one time)
import java.net.*;
import java.io.*;
class GpcSocket {
private Socket socket;
// default value
private int SERVER_PORT = 9999;
private String SERVER_IP = "192.168.3.100";
OutputStream out = null;
InputStream in = null;
byte[] buffer = new byte[157*10];
public GpcSocket(String serverIP, int serverPort) {
this.SERVER_PORT = serverPort;
this.SERVER_IP = serverIP;
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVER_PORT);
}
public int send(byte[] str) throws IOException {
out = socket.getOutputStream();
out.write(str);
out.flush();
// out.close();
return str.length;
}
public byte[] receive() throws IOException {
in = socket.getInputStream();
in.read(buffer);
in.close();
socket.close()
return this.buffer;
}
}
Related
Good day, I'm a beginner developer and I'm trying to write a client-server application. My application should work like this, it checks if the file has been modified and if so, it is sent to the server, the question is how to organize this?
I did it through the socket, but if I get a deadlock, I will be grateful for any comments, I attach the code further
Server
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket;
Socket client;
BufferedInputStream clientInputStream;
ByteArrayOutputStream byteArrayOutputStream;
StringBuilder fileName;
byte[] mass;
{
fileName = new StringBuilder("this.txt"); // give name for file
serverSocket = new ServerSocket(5000); // open server in 5000 port
mass = new byte[1]; // create new buffer array
client = serverSocket.accept(); // waiting connect
clientInputStream = new BufferedInputStream(client.getInputStream()); // to accept byte's array
byteArrayOutputStream = new ByteArrayOutputStream(); // to write byte array in file
}
{
BufferedOutputStream bufferedOutputStream;
int bytesRead;
// FIXME: 02.07.2022 первый файл
do {
byteArrayOutputStream.write(mass, 0, mass.length); // write by one byte in array
bytesRead = clientInputStream.read(mass, 0, mass.length);
} while (bytesRead != -1);
FileOutputStream writer = new FileOutputStream(fileName.toString()); // stream for file write
bufferedOutputStream = new BufferedOutputStream(writer);
bufferedOutputStream.write(byteArrayOutputStream.toByteArray(), 0, byteArrayOutputStream.toByteArray().length); // write file
System.out.println("first f");
bufferedOutputStream.flush();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
bufferedWriter.write("success"); // if file send success then write string in socket and send to client
}
{
serverSocket.close();
client.close();
clientInputStream.close();
byteArrayOutputStream.close();
}
}
}
And Client
import java.io.*;
import java.net.Socket;
public class Client {
private final static String serverIP = "192.168.0.47"; // server ip address
private final static int serverPort = 5000; // server port address
private final static String fileOutput = "first.txt"; // first file to send
private final static String fileOutput1 = "second.txt"; // second file to send
public static void main(String[] args) throws IOException, InterruptedException{
Socket client = new Socket(serverIP,serverPort); // make new connect with my server
BufferedInputStream inputFile = new BufferedInputStream(new FileInputStream(fileOutput)); // convert file to array bytes
// FIXME: 02.07.2022 first file
BufferedOutputStream clientSocketOutputWriter = new BufferedOutputStream(client.getOutputStream()); // this is the stream to send to the socket
byte[] massByte = inputFile.readAllBytes(); // this going on convert file to array bytes
clientSocketOutputWriter.write(massByte,0, massByte.length); // send array bytes to server
System.out.println("first file send");
//----------------if i remove this two string, program begin work successfully but i can't send several file because this beging deadlock
// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// String s = bufferedReader.readLine();
//----------------
System.out.println("the end");
clientSocketOutputWriter.close();
client.close();
inputFile.close();
}
}
If the TCP connection isn't closed,The variable bytesRead will never be -1 because the code clientInputStream.read(mass, 0, mass.length); keeps executing and waiting for data.If you want to send a file,you should send its length first then you can call byte[] data=clientInputStream.readNBytes(its length),or put its data into a object and use ObjectInputStream and ObjectOutputStream to send the object.
The variable bytesRead isn't -1 means the server cannot leave the loop,so the server cannot put the data which it has just received into a file.Just use writer.write(mass); instead of byteArrayOutputStream.write(mass, 0, mass.length);,write the data to the file directly then stop running the program can solve the problem too.
I have a project require using UDP protocol to transfer file but still guaranty the feature of TCP protocol. That means we have the speed of UDP and the file not lost.
I've already have:
Server:
public class UDPServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
int port = 6788;
DatagramSocket sk = new DatagramSocket(port);
byte[] buf = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buf, buf.length);
sk.receive(request);
String msg = (new String(request.getData()));
DatagramPacket reply = new DatagramPacket(msg.getBytes(), msg.getBytes().length, request.getAddress(), request.getPort());
sk.send(reply);
}
}
}
Client:
public class UDPClient {
public static void main(String[] args) throws SocketException, UnknownHostException, IOException {
DatagramSocket sk = new DatagramSocket();
String msg = "message send";
InetAddress addr = InetAddress.getByName("localhost");
int port = 6788;
DatagramPacket request = new DatagramPacket(msg.getBytes(), msg.getBytes().length, addr, port);
sk.send(request);
byte[] buf = new byte[1000];
DatagramPacket reply = new DatagramPacket(buf, buf.length);
sk.receive(reply);
System.out.println("packet da nhan duoi client" + new String(reply.getData()));
sk.close();
}
}
and can you help me any suggest to guaranty file not lost ?. tks
You have quite big task, if you really want to implement fast and reliable file transfer with UDP.
With very small files (that fits in a single IP packet), it could be easy to avoid some overhead of TCP (like TCP connection opening and closing handshakes).
But If you are going to transfer bigger files, then you must implement many difficult features, like: flow control, selective acknowledges, re-transmissions and so on.
So I suggest to use TCP, instead of implementing own similar protocol.
You just CAN'T. It's not designed to be reliable.
If you manage to do it... it just means that you've implemented TCP yourself!, it will be much slower though.
I'm developing a server to client file transfer program on java, and couldn't figure out how to fix the following code as I don't know much about socket programming. The code is Client side's codes:
String receiverIP = null;
int serverPort = 0;
hostIP = args[0];
serverPort = Integer.parseInt(args[1]);
String fileToSend = args[2];
byte[] aByte = new byte[1];
int bytesR;
Socket clientSocket = null;
Socket connectSocket = null;
BufferedOutputStream ToClient = null;
InputStream is = null;
try {
ToClient = new BufferedOutputStream(connectSocket.getOutputStream());
clientSocket = new Socket(hostIP, serverPort);
is = clientSocket.getInputStream();
} catch (IOException ex) {
System.out.println(ex);
}
as for my problem, I get a null pointer exception on line 14 (undoubtedly since currently connectSocket is null), but I have no idea what can I assign on connectSocket(if it was on server side a connection accept socket could've been assigned to begin writing after the connecion is established.)
Contrary to what you seem to believe, you do not need two separate sockets to read and write to the server. One socket will suffice. You can call the getInputStream method to get a stream to read from the server, and getOutputStream to get a stream to write to the server. You don't need two sockets, just one.
I have some problems with my server socket. I create a DatagramSocket to chat between a server and a client.
public static void main (String[] args) throws IOException {
byte[] send = new byte[1024];
byte[] receive = new byte[1024];
BufferedReader entree;
DatagramSocket serverSocket = null;
InetAddress ip;
InetAddress ipDest;
int port;
try {
serverSocket = new DatagramSocket(8888);
} catch (SocketException e) {
e.printStackTrace();
}
while (true) {
DatagramPacket recu = new DatagramPacket(receive, receive.length);
serverSocket.receive(recu);
String sentence = new String(recu.getData());
ipDest = recu.getAddress();
port = recu.getPort();
System.out.println("Reçu:"+sentence);
entree = new BufferedReader(new InputStreamReader(System.in));
String chaine = entree.readLine();
send = chaine.getBytes();
DatagramPacket dp = new DatagramPacket(send, send.length, ipDest, port);
serverSocket.send(dp);
send = new byte[1024];
receive = new byte[1024];
}
But I use new BufferedReader(new InputStreamReader(System.in)) get the next stuff to send, and it is blocking. So, I cannot receive what's comming from the client and print it.
How can I arrange this ?
Merci, eo
Trying to do non-blocking reads on System.in in Java is an exercise in futility. There's no portable way to do it, so Java doesn't support it.
Even if you create a separate thread and do a blocking read there, you'll have the problem of that thread being non-interruptible. See: Java: how to abort a thread reading from System.in
Basically, you either need to use a platform specific library (JNI) (JCurses for linux, for example), or use a GUI.
Edit to add: What you can do is move your socket reading to a different thread, as that is interruptible.
I've been trying for a while a few different methods to get my custom proxy to work, and the only way I've been able to so far is through use of Apache's HttpClient. However, for the sake of knowing, I was wondering why I'm having trouble with my own proxy handle implementation below:
public void processProxyRequest (Socket client, String request) throws Exception {
if ( !request.equals("") ) {
String[] requestHeaders = request.split("\\r\\n");
Pattern p = Pattern.compile("([A-Z]*)\\s*([^:\\/]*):\\/\\/([^\\s]*)\\s*(?:HTTP.*)");
Matcher m = p.matcher(requestHeaders[0]);
if ( m.matches() ) {
String method = m.group(1).toUpperCase();
String proto = m.group(2).toLowerCase();
String[] requestInfo = m.group(3).split("\\/", 2);
String host = requestInfo[0];
host = ( host.split("\\.").length < 3 ) ? "www." + host : host;
String page = "/";
if ( requestInfo.length == 2 && !requestInfo[1].equals("") ) {
page += requestInfo[1];
}
int remotePort = 80;
if ( proto.equals("https") ) {
remotePort = 443;
}
else if ( proto.equals("ftp") ) {
remotePort = 21;
}
this.sendAndReceive(client, request, host, remotePort);
}
}
}
public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
Socket target = new Socket(host, port);
System.out.println("Connected to server");
ByteArrayInputStream inStream = new ByteArrayInputStream(request.getBytes());
this.inToOut(inStream, target.getOutputStream());
System.out.println("Sent");
this.inToOut(target.getInputStream(), client.getOutputStream());
System.out.println("Received");
target.close();
}
public void inToOut (InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
System.out.println("reading");
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
In a nutshell (and disregarding my request header parsing flaws), the above code compiles and runs, however, the inToOut() method seems to struggle a bit and lock up during the input.read(), and I'm not too sure why. I do know as a fact that the original socket I'm passing in is valid and opened without errors. Additionally, the System.out in the inToOut() function does print "reading" but never gets past the read() portion.
Thank you for any suggestions!
This is no way to write a proxy. In the case of HTTP you only have to process the first line, that tells you the target host. Everything else is just copying bytes back and forth, subject to a couple of minor refinements such as reporting upstream connect errors correctly snd handling shutdowns properly. The FTP case is trickier and should be handled completely separately, but again once you get past the connect phase it's just copying bytes around. The less effortmyou make to understand the protocol the simpler and better it gets.
In your sendAndReceive function, perhaps try using DataInputStream and DataOutputStream
public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
Socket target = new Socket(host, port);
System.out.println("Connected to server");
this.inToOut(new DataInputStream(client.getInputStream()), new DataOutputStream(target.getOutputStream()));
System.out.println("Sent");
this.inToOut(new DataInputStream(target.getInputStream()), new DataOutputStream(client.getOutputStream()));
System.out.println("Received");
target.close();
}
The problem doesn't seem to be in the inToOut function - I've tried using inToOut() and it works fine (it actually helped me fix a problem I was having with something similar - Thanks)