La gestión de las conexiones se hace en un único hilo, por lo que si dos peticiones de diferentes clientes llegan a la vez, una se perderá
TCP
Estos códigos contienen una clase donde he implementado diferentes métodos según las acciones posibles a través de los sockers
Servidor
package src;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_Server {
private int port;
ServerSocket serverSocket;
Socket clientSocket;
/**
* Constructor. Creates a new server socket and binds it to the specified port. This method wont accept any incoming connections.
*
* @param port The port to bind the server socket to
* @throws IOException If an I/O error occurs
*/
public TCP_Server(int port) throws IOException {
this.port = port;
serverSocket = new ServerSocket(1234);
}
/**
* Accepts an incoming connection. This method will block until a connection is made.
*
* @throws IOException If an I/O error occurs
*/
public void accept() throws IOException {
clientSocket = serverSocket.accept();
}
// ==========================================[ COMMUNICATION METHODS ]==================================================
// ----------------------------------------[ Bytes methods ]--------------------------------------------------
/**
* Reads an array of bytes from the client. This method will block until the client sends all the expected bytes.
*
* @param nBytes The number of bytes we want to read
* @return The data sent by the client
* @throws IOException
*/
public byte[] recvBytes(int nBytes) throws IOException {
InputStream recvPipe = clientSocket.getInputStream();
// Buffer to store the data
byte buffer[] = new byte[nBytes];
// Read the data and store them in the buffer (returns the number of bytes read)
int bytesRead = recvPipe.read(buffer);
// Copy the data from the buffer to a new array of the exact size
byte data[] = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++) {
data[i] = buffer[i];
}
// If the server didn't send any data, return null
if (bytesRead == -1) {
return null;
}
// Return the data
else {
return data;
}
}
/**
* Sends an array of bytes to the client.
*
* @param data The data we want to send as an array of bytes
* @throws IOException If an I/O error occurs
*/
public void sendBytes(byte[] data) throws IOException {
// Send the data
OutputStream outputStream = clientSocket.getOutputStream();
outputStream.write(data);
}
// ----------------------------------------[ String methods ]--------------------------------------------------
/**
* Reads a string from the client. This method will block until the client sends the '\n' character.
*
* @return The string sent by the client
* @throws IOException
*/
public String recvStringLine() throws IOException {
InputStreamReader clientInput = new InputStreamReader(clientSocket.getInputStream());
BufferedReader inputBuffer = new BufferedReader(clientInput);
// Read the data and store them in the buffer (returns the number of bytes read)
String line = inputBuffer.readLine();
return line;
}
/**
* Sends a string to the client.
*
* @param msg The message we want to send as a string
* @throws IOException If an I/O error occurs
*/
public void sendString(String msg) throws IOException {
// Send the data
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
outputStream.writeBytes(msg);
}
// ----------------------------------------[ File methods ]--------------------------------------------------
/**
* Sends a file to the client.
*
* @param path
* @throws IOException
*/
public void sendFile(String path) throws IOException {
// Writter to send the file over the socket
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
// Read the file
BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(path)));
System.out.println("Sending file: " + path);
// Read the file line by line and send it to the client
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
}
System.out.println("File sent.");
// Close the file
reader.close();
writer.close();
}
// ==========================================[ CLOSE ]==================================================
/**
* Closes the server socket.
*
* @throws IOException
*/
public void closeServer() throws IOException {
serverSocket.close();
}
/**
* Closes the client socket.
*
* @throws IOException
*/
public void closeClient() throws IOException {
clientSocket.close();
}
// ==========================================[ SERVER OPERATION ]==================================================
// Premade methods to be used by the server when a some data is received from the client
public void serverOperation(String sentence) throws IOException {
String newSentence = sentence.toUpperCase() + '\n';
sendString(newSentence);
}
public void serverOperation(byte[] data) throws IOException {
for (int i = 0; i < data.length; i++) {
data[i] = (byte) (data[i] + 1);
}
sendBytes(data);
}
// ==========================================[ DEBUG METHODS ]==================================================
/**
* The purpose of this method is to debug the server. It will echo the uppercase of the received string back to the client.
*
* @throws IOException If an I/O error occurs
*/
public void echoLines() throws IOException {
while (true) {
try {
// Accept the incoming connection
accept();
System.out.println("Connection accepted...");
// Receive the data
String sentence = recvStringLine();
// OPERATION DONE AT THE SERVER
serverOperation(sentence);
// ----------------------------
// Close the connection (send to the client the '-1' message to close the connection)
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* The purpose of this method is to debug the server. It will echo the received (byte+1) back to the client.
*
* @throws IOException If an I/O error occurs
*/
public void echoByte() throws IOException {
while (true) {
try {
// Accept the incoming connection
accept();
System.out.println("Connection accepted...");
// Receive the data
byte data[] = recvBytes(1);
// OPERATION DONE AT THE SERVER
serverOperation(data);
// ----------------------------
// Close the connection (send to the client the '-1' message to close the connection)
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* The purpose of this method is to debug the server. It will echo the received file back to the client.
*
* The server will expect the client to send a byte.
*
* 0x00: The server will receive a string, and will echo it back to the client in uppercase.
* 0x01: The server will receive a byte, and will echo it back to the client +1.
* 0x02: The server will send a file to the client.
*
* @throws IOException
*/
public void debug() throws IOException {
while (true) {
System.out.println("Waiting for a connection...");
// Accept the incoming connection
accept();
System.out.println("Connection accepted...");
// Receive 1 byte from the client
byte opt = recvBytes(1)[0];
System.out.println("Option received: " + opt);
// Do something with the data received (0=String, 1=byte, 2=File)
if (opt == 0) {
// Echo the received string
String str = recvStringLine();
serverOperation(str);
} else if (opt == 1) {
// Echo the received byte
byte data[] = recvBytes(1);
serverOperation(data);
} else if (opt == 2) {
// Send a file to the client
sendFile("resources/file.txt");
}
System.out.println("Operation done.");
// Close the connection with the client
closeClient();
}
}
// ==========================================[ GETTERS AND SETTERS ]==================================================
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
Cliente
package src;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
/**
* TCP_Client
*/
public class TCP_Client {
private String ip;
private int port;
Socket socket;
InputStream recvPipe;
OutputStream sendPipe;
/**
* Constructor for the
*
* @param ip The IP address of the server
* @param port The port of the server
* @throws IOException
*/
public TCP_Client(String ip, int port) throws IOException {
this.ip = ip;
this.port = port;
socket = new Socket(ip, port);
recvPipe = socket.getInputStream();
sendPipe = socket.getOutputStream();
}
/*
* Close the socket
*/
public void close() throws IOException {
socket.close();
}
// =================================================[ Send and receive methods ]=================================================
// ------------------------------------- Bytes messages -------------------------------------
/**
* Send an array of bytes to the server
*
* @param data The data to send
* @throws IOException
*/
public void sendBytes(byte data[]) throws IOException {
// Send the data
sendPipe.write(data);
}
/**
* Read all available bytes from the server. The response wont be processed until the server closes the current client socket.
*
* Use the getBlockSize() method and the setBlockSize() method to change the block size
*
* @return An array of bytes with the data received. If the server didn't send any data, returns null
* @throws IOException
*/
public byte[] recvBytes() throws IOException {
// Create an input buffer of dynamic size
ArrayList<Byte> buffer = new ArrayList<Byte>();
// Read the data and store them in the buffer (returns the number of bytes read)
int byteRead = recvPipe.read();
// If the server didn't send any data, return null
if (byteRead == -1) {
return null;
}
// Read the data until the server doesn't send any data
while (byteRead != -1) {
// Add the data to the buffer
buffer.add((byte) byteRead);
// Read the next byte
byteRead = recvPipe.read();
}
// Copy the data from the buffer to a new array of the exact size
byte data[] = new byte[buffer.size()];
for (int i = 0; i < buffer.size(); i++) {
data[i] = buffer.get(i);
}
// Return the data
return data;
}
/**
* Read an specific number of bytes from the server. Wait until the server sends the data
*
* @param size The number of bytes to read
* @throws IOException
*/
public byte[] recvBytes(int size) throws IOException {
// Buffer to store the data
byte buffer[] = new byte[size];
// Read the data and store them in the buffer (returns the number of bytes read)
int totalBytesRead = 0;
// Read the data until the total number of bytes read is equal to the size
while (totalBytesRead < size) {
// Read the data and store them in the buffer (returns the number of bytes read)
int bytesRead = recvPipe.read(buffer);
// If the server didn't send any data, try again
if (bytesRead == -1) {
continue;
}
// Dump the data read on this loop to the buffer
for (int i = 0; i < bytesRead; i++) {
buffer[totalBytesRead + i] = buffer[i];
}
// Update the total number of bytes read
totalBytesRead += bytesRead;
}
// Copy the data from the buffer to a new array of the exact size
return buffer;
}
// ------------------------------------- String messages -------------------------------------
/**
* Send a message to the server
*
* @param msg The message to send
* @throws IOException
*/
public void sendString(String msg) throws IOException {
// Prepare the data to send
byte data[] = msg.getBytes();
// Send the data
sendPipe.write(data);
}
/**
* Read a line from the server. The response wont be processed until the server closes the current client socket.
*
* @return The line received from the server
* @throws IOException
*/
public String recvStringLine() throws IOException {
InputStreamReader in = new InputStreamReader(socket.getInputStream());
BufferedReader buff = new BufferedReader(in);
// Read the data and store them in the buffer (returns the number of bytes read)
String line = buff.readLine();
return line;
}
/**
* Read a file from the server. The response wont be processed until the server closes the current client socket.
*
* @param filename
* @throws IOException
*/
public void recvFile(String filename) throws IOException {
// Prepare the file to write the response
FileOutputStream file = new FileOutputStream(filename);
// Read the response
byte data[] = recvBytes();
file.write(data);
// Close the file
file.close();
}
// =================================================[ Getters and setters ]=================================================
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
UDP
Estos códigos son un ejemplo de uso para establecer una conexión UDP
Servidor
class UDPServidor {
public static void main(String args[]) throws Exception {
DatagramSocket socket = new DatagramSocket(1234);
byte[] inBuffer = new byte[1024];
while(true) {
//Recibe el datagrama
DatagramPacket inPack = new DatagramPacket(inBuffer, inBuffer.length);
socket.receive(inPack);
//Transforma los datos
String frase = new String(inPack.getData());
String modifiedSentence = sentence.toUpperCase();
byte[] outBuffer = modifiedSentence.getBytes();
//Envía el datagrama a la dirección que llegó con el paquete
InetAddress dirIP = inPack.getAddress();
int port = inPack.getPort();
DatagramPacket outPack = new DatagramPacket(outBuffer,outBuffer.length,dirIP,port);
socket.send(outPack);
}
}
}
Cliente
class UDPCliente {
public static void main(String args[]) throws Exception {
//Creamos datagrama de salida con el mensaje
InetAddress dirIP = InetAddress.getByName("192.156.21.21");
String sentence = "Mensaje que se desea enviar";
byte[] outBuff = sentence.getBytes();
DatagramPacket outPac = new DatagramPacket(outBuff,outBuff.length,dirIP,1234);
//Creamos el socket y enviamos el datagrama
DatagramSocket socket= new DatagramSocket();
socket.send(outPac);
//Recibimos un datagrama
byte[] inputBuff = new byte[1024];
DatagramPacket inPac = new DatagramPacket(inputBuff, inputBuff.length);
socket.receive(inPac);
socket.close();
String newSentence = new String(inPac.getData());
System.out.println("DEL SERVIDOR:" + newSentence);
}
}