SlideShare ist ein Scribd-Unternehmen logo
1 von 4
Downloaden Sie, um offline zu lesen
Código Java Oracle
Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO...
http://codigojavaoracle.com

Cómo crear un Socket TCP en Java
En este artículo mostramos el código necesario para crear un Socket TCP (Orientado a
Conexión) realizado en Java.
Cómo ya sabéis el protocolo TCP está orientado a conexión, para más información podéis ver
este link.

Socket TCP
Basicamente, este es el funcionamiento de los Socket que necesitamos para una conexión
TCP. En el que podemos distinguir dos tipos de Socket el del Servidor y el del Cliente.
La creación del socket en el servidor se remite a crear el socket, indicar por que puerto se
harán las escuchas y esperar a la llamada de un cliente para aceptar la conexión, en cambio un
cliente creará el socket e indicará donde se encuentra y por que puerto quiere conectarse, de
está forma Cliente y Servidor crearán una conexión.
Servidor:
Para crear los socket se crea un objeto del tipo ServerSocket, este método pertenece a la
clase java.net.Serversocket
Una vez que hemos creado el objeto socket mandamos un parámetro que indicará el puerto
por el que se realzará las comunicaciones.
Para realizar una conexión entre Cliente-Servidor, el servidor usará el método socket.accept
para confirmar que se ha iniciado la conexión.
Cliente:
Primero crea un objeto del tipo Socket que pertenece a la clase java.net.Serversocket,
Después se obtiene un objeto InetAddress, y usando el método getByName le indicamos
donde se va a ejecutar el cliente, en nuestro caso indicamos que será en localhost.
Finalmente creamos un objeto de tipo socket al que pasaremos la dirección donde se está
ejecutando el cliente, y el puerto por donde se conectará al servidor.
Código del Servidor:
import java.net.*; //Importa la libreria java.net import java.io.
*; //Importa la libreria java.io
public class servidortcp {
//
se declara una clase de nombre servidortcp
public static void mai
n(String argv[]) {
//Se declara el método principal main

1/4
Código Java Oracle
Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO...
http://codigojavaoracle.com

que espera un parámetro
System.out.println("SERVIDOR");
ServerSocket socket;
//Se crea un objeto de ServerSocket
//b
oolean fin = false; //Se declara una variable booleana inicializada a
false
try {
//Abrimos una exceptción para el
tratamiento de errores
//Creamos un servidor
socke
t = new ServerSocket(6004); //Abre un socket en modo escucha en el pue
rto 6001
Socket socket_cli = socket.accept(); //Inicio.Se a
cepta la conexión.
//Método de la clase socket pa
ra recibir datos
DataInputStream in =
new DataI
nputStream(socket_cli.getInputStream());
//Método
para mandar un valor al cliente
DataOutputStream out =
new DataOutputStream(socket_cli.getOutputStream());
String mensaje =""; //Se inicializa la variabl
e de string mensaje a vacío
mensaje = in.readUTF(); //La var
iable Mensaje guarda el valor que ha mandado el cliente
if (mensaje.startsWith("HELLO")) {
out.writeUTF("HEL
LO");
}
do {
//Est
ará escuchando el mensaje sin interrupción debido a la condición (1>0)
del while
mensaje =""; //Se inicializa la variable de st
ring mensaje a vacío
mensaje = in.readUTF(); //La variabl
e Mensaje guarda el valor que ha mandado el cliente
if (mensaje.startsWith("ALL")) {
mensaje = "ALL BUR:250;CHE:300; BIG:540; PAT:380; SAL:240; BEV:210; D
IE:0; COF:0; DES:300";
System.out.println(mensaje);
}
else if(mensaje.startsWith("BUR
"))
{
mensaje = "BUR 250";
Sy
stem.out.println(mensaje);
}
else if (mensaj
e.startsWith("CHE")) {
mensaje = "CHE 300";
System.out.println(mensaje);
}
else if (me
nsaje.startsWith("BIG")) {
mensaje= "BIG 540";
System.out.println(mensaje);
}
else if
(mensaje.startsWith("PAT")) {
mensaje= "PAT 380";
System.out.println(mensaje);
}
else
if (mensaje.startsWith("SAL")) {
mensaje= "SAL 240";
System.out.println(mensaje);
}
el
se if (mensaje.startsWith("BEV")) {
mensaje= "SAL 210";
System.out.println(mensaje);
}
else if (mensaje.startsWith("DIE")) {
mensaje= "DIE 0";
System.out.println(mensaje);
}
else if (mensaje.startsWith("COF")) {
mensaje= "COF 0"
;
System.out.println(mensaje);
}
else if (mensaje.startsWith("DES")) {
mensaje= "DES 3
00";
System.out.println(mensaje);
}
else if (mensaje.startsWith("fin")) {
mensaje= "fi
n";
System.out.println(mensaje);
}
else{
mensaje = "ERROR";
System.o

2/4
Código Java Oracle
Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO...
http://codigojavaoracle.com

ut.println(mensaje);
}
//Manda
mos al cliente la respuesta de las calorias según lo que ha mandado
out.writeUTF(mensaje);
//System.out.printl
n(mensaje);
} while (1>0);
}
c
atch (Exception e) {
//Si se produce algún error saltará la ex
cepción con el mensaje de error
System.err.println(e.getMess
age());
System.exit(1); //Salimos con error
}
}
}

Código del Cliente:
import java.net.*; //Se importa la libreria java.net import java.
io.*; //Se importa la libreria java.io
//Se declara la clase client
etcp public class clientetcp {
//Se declara el método principal
main que recibe un parámetro
public static void main(String argv[]
) {
//Si no recibe ningún parámetro dará error
if (arg
v.length == 0) {
System.err.println("java clientetcp servido
r");
System.exit(1);
}
System.out.println(
"CLIENTE");
// Se guarda en el buffer un valor introducido p
or pantalla
BufferedReader in = new BufferedReader(new InputS
treamReader(System.in));
Socket socket=null; //Se crea un obj
eto de tipo socket
InetAddress address; //Se crea un objeto de
tipo InetAddress
String mensaje=""; //Se declara una variable d
e tipo string
try {
//Se abre una excepción
//Obtiene el nombre de la dirección remota del socket
a
ddress=InetAddress.getByName(argv[0]);
try{
soc
ket = new Socket(address,Integer.parseInt(argv[1])); //Se crea un obje
to de tipo socket
//para
establecer una conexión por el puerto 6001
}catch(NumberFor
matException nfe){
System.err.println("El argumento argv[1]
no es un numero");
System.exit(1);
}
//Se declara un objeto de tipo DataOutputStream para mandar valores a
l servidor
DataOutputStream out =
new DataOutp
utStream(socket.getOutputStream());
//Se declara un objeto
de tipo DataOutputStream para mandar obtener al servidor
Da
taInputStream in2 =
new DataInputStream(socket.getInputS
tream());
//Mandamos la palabra HELLO al servidor
out.writeUTF("HELLO");
//Recogemos lo que nos dev
uelve el servidor y lo guardamos en la variable mensaje
mens
aje = in2.readUTF();
System.out.println(mensaje); //Imprime
el contenido de mensaje
do {
//Mientra
s el mensaje no sea fin seguira leyendo
mensaje = in.read
Line();
out.writeUTF(mensaje);
//System.out.
println(mensaje); //Imprime el contenido de mensaje

3/4
Código Java Oracle
Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO...
http://codigojavaoracle.com

//NUEVO
mensaje =""; //Se inicializa la variable de
string mensaje a vacío
mensaje = in2.readUTF();
System.out.println(mensaje); //Imprime el contenido de mensaje
//NUEVO
} while (!mensaje.startsWith("fi
n"));
}
catch (Exception e) {
System.err.print
ln(e.getMessage());
System.exit(1);
}
} }

4/4
Powered by TCPDF (www.tcpdf.org)

Weitere ähnliche Inhalte

Andere mochten auch

1396 p1-spk-teknik konstruksi kapal baja
1396 p1-spk-teknik konstruksi kapal baja1396 p1-spk-teknik konstruksi kapal baja
1396 p1-spk-teknik konstruksi kapal bajaWinarto Winartoap
 
6045 p1-p psp-adminisitrasi perkantoran
6045 p1-p psp-adminisitrasi perkantoran6045 p1-p psp-adminisitrasi perkantoran
6045 p1-p psp-adminisitrasi perkantoranWinarto Winartoap
 
бизнес-центр «Север»
бизнес-центр «Север»бизнес-центр «Север»
бизнес-центр «Север»Anna Korogodina
 
6036 p3-p psp-perbankan syariah
6036 p3-p psp-perbankan syariah6036 p3-p psp-perbankan syariah
6036 p3-p psp-perbankan syariahWinarto Winartoap
 
1769 p2-p psp-teknik dan manajemen transportasi
1769 p2-p psp-teknik dan manajemen transportasi1769 p2-p psp-teknik dan manajemen transportasi
1769 p2-p psp-teknik dan manajemen transportasiWinarto Winartoap
 
4169 p123-p psp-seni pedalangan yogyakarta
4169 p123-p psp-seni pedalangan yogyakarta4169 p123-p psp-seni pedalangan yogyakarta
4169 p123-p psp-seni pedalangan yogyakartaWinarto Winartoap
 
1378 p3-spk-kelistrikan pesawat udara
1378 p3-spk-kelistrikan pesawat udara1378 p3-spk-kelistrikan pesawat udara
1378 p3-spk-kelistrikan pesawat udaraWinarto Winartoap
 
Intelligence strategic
Intelligence strategicIntelligence strategic
Intelligence strategicIonel Nitu
 
3032 p2-p psp-analis kesehatan
3032 p2-p psp-analis kesehatan3032 p2-p psp-analis kesehatan
3032 p2-p psp-analis kesehatanWinarto Winartoap
 
4098 p2-p psp-desain dan produksi kria logam
4098 p2-p psp-desain dan produksi kria logam4098 p2-p psp-desain dan produksi kria logam
4098 p2-p psp-desain dan produksi kria logamWinarto Winartoap
 
2036 p1-p psp-teknik suitsing
2036 p1-p psp-teknik suitsing2036 p1-p psp-teknik suitsing
2036 p1-p psp-teknik suitsingWinarto Winartoap
 
5263 p2-p psp-agribisnis tanaman pangan dan holtikultura
5263 p2-p psp-agribisnis tanaman pangan dan holtikultura5263 p2-p psp-agribisnis tanaman pangan dan holtikultura
5263 p2-p psp-agribisnis tanaman pangan dan holtikulturaWinarto Winartoap
 
6036 p2-spk-perbankan syariah
6036 p2-spk-perbankan syariah6036 p2-spk-perbankan syariah
6036 p2-spk-perbankan syariahWinarto Winartoap
 
5254 p1-p psp-perawatan kesehatan ternak
5254 p1-p psp-perawatan kesehatan ternak5254 p1-p psp-perawatan kesehatan ternak
5254 p1-p psp-perawatan kesehatan ternakWinarto Winartoap
 

Andere mochten auch (16)

1396 p1-spk-teknik konstruksi kapal baja
1396 p1-spk-teknik konstruksi kapal baja1396 p1-spk-teknik konstruksi kapal baja
1396 p1-spk-teknik konstruksi kapal baja
 
6045 p1-p psp-adminisitrasi perkantoran
6045 p1-p psp-adminisitrasi perkantoran6045 p1-p psp-adminisitrasi perkantoran
6045 p1-p psp-adminisitrasi perkantoran
 
бизнес-центр «Север»
бизнес-центр «Север»бизнес-центр «Север»
бизнес-центр «Север»
 
6036 p3-p psp-perbankan syariah
6036 p3-p psp-perbankan syariah6036 p3-p psp-perbankan syariah
6036 p3-p psp-perbankan syariah
 
1769 p2-p psp-teknik dan manajemen transportasi
1769 p2-p psp-teknik dan manajemen transportasi1769 p2-p psp-teknik dan manajemen transportasi
1769 p2-p psp-teknik dan manajemen transportasi
 
4169 p123-p psp-seni pedalangan yogyakarta
4169 p123-p psp-seni pedalangan yogyakarta4169 p123-p psp-seni pedalangan yogyakarta
4169 p123-p psp-seni pedalangan yogyakarta
 
1378 p3-spk-kelistrikan pesawat udara
1378 p3-spk-kelistrikan pesawat udara1378 p3-spk-kelistrikan pesawat udara
1378 p3-spk-kelistrikan pesawat udara
 
1334 p3-spk-krpu
1334 p3-spk-krpu1334 p3-spk-krpu
1334 p3-spk-krpu
 
Intelligence strategic
Intelligence strategicIntelligence strategic
Intelligence strategic
 
3032 p2-p psp-analis kesehatan
3032 p2-p psp-analis kesehatan3032 p2-p psp-analis kesehatan
3032 p2-p psp-analis kesehatan
 
4098 p2-p psp-desain dan produksi kria logam
4098 p2-p psp-desain dan produksi kria logam4098 p2-p psp-desain dan produksi kria logam
4098 p2-p psp-desain dan produksi kria logam
 
2036 p1-p psp-teknik suitsing
2036 p1-p psp-teknik suitsing2036 p1-p psp-teknik suitsing
2036 p1-p psp-teknik suitsing
 
5263 p2-p psp-agribisnis tanaman pangan dan holtikultura
5263 p2-p psp-agribisnis tanaman pangan dan holtikultura5263 p2-p psp-agribisnis tanaman pangan dan holtikultura
5263 p2-p psp-agribisnis tanaman pangan dan holtikultura
 
Tugas tik
Tugas tikTugas tik
Tugas tik
 
6036 p2-spk-perbankan syariah
6036 p2-spk-perbankan syariah6036 p2-spk-perbankan syariah
6036 p2-spk-perbankan syariah
 
5254 p1-p psp-perawatan kesehatan ternak
5254 p1-p psp-perawatan kesehatan ternak5254 p1-p psp-perawatan kesehatan ternak
5254 p1-p psp-perawatan kesehatan ternak
 

Kürzlich hochgeladen

periodico para ingles / comunicacion.pdf
periodico para ingles / comunicacion.pdfperiodico para ingles / comunicacion.pdf
periodico para ingles / comunicacion.pdfacoellob
 
Catalogo de diseño contemporáneo relevante
Catalogo de diseño contemporáneo relevanteCatalogo de diseño contemporáneo relevante
Catalogo de diseño contemporáneo relevantesantiagovelez61
 
Espiraleros y espirales (3) catálogo.pdf
Espiraleros y espirales (3) catálogo.pdfEspiraleros y espirales (3) catálogo.pdf
Espiraleros y espirales (3) catálogo.pdfjpgaraglia03
 
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...Artículo Iluminación y color para el diseño de espacios interiores por Oriett...
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...ORIETTA POLIFRONI
 
diseño módulos, submódulos y supermódulos.pptx
diseño módulos, submódulos y supermódulos.pptxdiseño módulos, submódulos y supermódulos.pptx
diseño módulos, submódulos y supermódulos.pptxlou lou
 
elementos del diseño bases conceptuales, visuales, etc.pptx
elementos del diseño bases conceptuales, visuales, etc.pptxelementos del diseño bases conceptuales, visuales, etc.pptx
elementos del diseño bases conceptuales, visuales, etc.pptxlou lou
 
Simuladores Electronicos Del Circuito Electronicos
Simuladores Electronicos Del Circuito ElectronicosSimuladores Electronicos Del Circuito Electronicos
Simuladores Electronicos Del Circuito ElectronicosErickOv
 

Kürzlich hochgeladen (7)

periodico para ingles / comunicacion.pdf
periodico para ingles / comunicacion.pdfperiodico para ingles / comunicacion.pdf
periodico para ingles / comunicacion.pdf
 
Catalogo de diseño contemporáneo relevante
Catalogo de diseño contemporáneo relevanteCatalogo de diseño contemporáneo relevante
Catalogo de diseño contemporáneo relevante
 
Espiraleros y espirales (3) catálogo.pdf
Espiraleros y espirales (3) catálogo.pdfEspiraleros y espirales (3) catálogo.pdf
Espiraleros y espirales (3) catálogo.pdf
 
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...Artículo Iluminación y color para el diseño de espacios interiores por Oriett...
Artículo Iluminación y color para el diseño de espacios interiores por Oriett...
 
diseño módulos, submódulos y supermódulos.pptx
diseño módulos, submódulos y supermódulos.pptxdiseño módulos, submódulos y supermódulos.pptx
diseño módulos, submódulos y supermódulos.pptx
 
elementos del diseño bases conceptuales, visuales, etc.pptx
elementos del diseño bases conceptuales, visuales, etc.pptxelementos del diseño bases conceptuales, visuales, etc.pptx
elementos del diseño bases conceptuales, visuales, etc.pptx
 
Simuladores Electronicos Del Circuito Electronicos
Simuladores Electronicos Del Circuito ElectronicosSimuladores Electronicos Del Circuito Electronicos
Simuladores Electronicos Del Circuito Electronicos
 

Creacion de-socket-tcp-en-java

  • 1. Código Java Oracle Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO... http://codigojavaoracle.com Cómo crear un Socket TCP en Java En este artículo mostramos el código necesario para crear un Socket TCP (Orientado a Conexión) realizado en Java. Cómo ya sabéis el protocolo TCP está orientado a conexión, para más información podéis ver este link. Socket TCP Basicamente, este es el funcionamiento de los Socket que necesitamos para una conexión TCP. En el que podemos distinguir dos tipos de Socket el del Servidor y el del Cliente. La creación del socket en el servidor se remite a crear el socket, indicar por que puerto se harán las escuchas y esperar a la llamada de un cliente para aceptar la conexión, en cambio un cliente creará el socket e indicará donde se encuentra y por que puerto quiere conectarse, de está forma Cliente y Servidor crearán una conexión. Servidor: Para crear los socket se crea un objeto del tipo ServerSocket, este método pertenece a la clase java.net.Serversocket Una vez que hemos creado el objeto socket mandamos un parámetro que indicará el puerto por el que se realzará las comunicaciones. Para realizar una conexión entre Cliente-Servidor, el servidor usará el método socket.accept para confirmar que se ha iniciado la conexión. Cliente: Primero crea un objeto del tipo Socket que pertenece a la clase java.net.Serversocket, Después se obtiene un objeto InetAddress, y usando el método getByName le indicamos donde se va a ejecutar el cliente, en nuestro caso indicamos que será en localhost. Finalmente creamos un objeto de tipo socket al que pasaremos la dirección donde se está ejecutando el cliente, y el puerto por donde se conectará al servidor. Código del Servidor: import java.net.*; //Importa la libreria java.net import java.io. *; //Importa la libreria java.io public class servidortcp { // se declara una clase de nombre servidortcp public static void mai n(String argv[]) { //Se declara el método principal main 1/4
  • 2. Código Java Oracle Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO... http://codigojavaoracle.com que espera un parámetro System.out.println("SERVIDOR"); ServerSocket socket; //Se crea un objeto de ServerSocket //b oolean fin = false; //Se declara una variable booleana inicializada a false try { //Abrimos una exceptción para el tratamiento de errores //Creamos un servidor socke t = new ServerSocket(6004); //Abre un socket en modo escucha en el pue rto 6001 Socket socket_cli = socket.accept(); //Inicio.Se a cepta la conexión. //Método de la clase socket pa ra recibir datos DataInputStream in = new DataI nputStream(socket_cli.getInputStream()); //Método para mandar un valor al cliente DataOutputStream out = new DataOutputStream(socket_cli.getOutputStream()); String mensaje =""; //Se inicializa la variabl e de string mensaje a vacío mensaje = in.readUTF(); //La var iable Mensaje guarda el valor que ha mandado el cliente if (mensaje.startsWith("HELLO")) { out.writeUTF("HEL LO"); } do { //Est ará escuchando el mensaje sin interrupción debido a la condición (1>0) del while mensaje =""; //Se inicializa la variable de st ring mensaje a vacío mensaje = in.readUTF(); //La variabl e Mensaje guarda el valor que ha mandado el cliente if (mensaje.startsWith("ALL")) { mensaje = "ALL BUR:250;CHE:300; BIG:540; PAT:380; SAL:240; BEV:210; D IE:0; COF:0; DES:300"; System.out.println(mensaje); } else if(mensaje.startsWith("BUR ")) { mensaje = "BUR 250"; Sy stem.out.println(mensaje); } else if (mensaj e.startsWith("CHE")) { mensaje = "CHE 300"; System.out.println(mensaje); } else if (me nsaje.startsWith("BIG")) { mensaje= "BIG 540"; System.out.println(mensaje); } else if (mensaje.startsWith("PAT")) { mensaje= "PAT 380"; System.out.println(mensaje); } else if (mensaje.startsWith("SAL")) { mensaje= "SAL 240"; System.out.println(mensaje); } el se if (mensaje.startsWith("BEV")) { mensaje= "SAL 210"; System.out.println(mensaje); } else if (mensaje.startsWith("DIE")) { mensaje= "DIE 0"; System.out.println(mensaje); } else if (mensaje.startsWith("COF")) { mensaje= "COF 0" ; System.out.println(mensaje); } else if (mensaje.startsWith("DES")) { mensaje= "DES 3 00"; System.out.println(mensaje); } else if (mensaje.startsWith("fin")) { mensaje= "fi n"; System.out.println(mensaje); } else{ mensaje = "ERROR"; System.o 2/4
  • 3. Código Java Oracle Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO... http://codigojavaoracle.com ut.println(mensaje); } //Manda mos al cliente la respuesta de las calorias según lo que ha mandado out.writeUTF(mensaje); //System.out.printl n(mensaje); } while (1>0); } c atch (Exception e) { //Si se produce algún error saltará la ex cepción con el mensaje de error System.err.println(e.getMess age()); System.exit(1); //Salimos con error } } } Código del Cliente: import java.net.*; //Se importa la libreria java.net import java. io.*; //Se importa la libreria java.io //Se declara la clase client etcp public class clientetcp { //Se declara el método principal main que recibe un parámetro public static void main(String argv[] ) { //Si no recibe ningún parámetro dará error if (arg v.length == 0) { System.err.println("java clientetcp servido r"); System.exit(1); } System.out.println( "CLIENTE"); // Se guarda en el buffer un valor introducido p or pantalla BufferedReader in = new BufferedReader(new InputS treamReader(System.in)); Socket socket=null; //Se crea un obj eto de tipo socket InetAddress address; //Se crea un objeto de tipo InetAddress String mensaje=""; //Se declara una variable d e tipo string try { //Se abre una excepción //Obtiene el nombre de la dirección remota del socket a ddress=InetAddress.getByName(argv[0]); try{ soc ket = new Socket(address,Integer.parseInt(argv[1])); //Se crea un obje to de tipo socket //para establecer una conexión por el puerto 6001 }catch(NumberFor matException nfe){ System.err.println("El argumento argv[1] no es un numero"); System.exit(1); } //Se declara un objeto de tipo DataOutputStream para mandar valores a l servidor DataOutputStream out = new DataOutp utStream(socket.getOutputStream()); //Se declara un objeto de tipo DataOutputStream para mandar obtener al servidor Da taInputStream in2 = new DataInputStream(socket.getInputS tream()); //Mandamos la palabra HELLO al servidor out.writeUTF("HELLO"); //Recogemos lo que nos dev uelve el servidor y lo guardamos en la variable mensaje mens aje = in2.readUTF(); System.out.println(mensaje); //Imprime el contenido de mensaje do { //Mientra s el mensaje no sea fin seguira leyendo mensaje = in.read Line(); out.writeUTF(mensaje); //System.out. println(mensaje); //Imprime el contenido de mensaje 3/4
  • 4. Código Java Oracle Programación, Java, Oracle, Php, JavaScript, Facebook API, WordPress, SEO... http://codigojavaoracle.com //NUEVO mensaje =""; //Se inicializa la variable de string mensaje a vacío mensaje = in2.readUTF(); System.out.println(mensaje); //Imprime el contenido de mensaje //NUEVO } while (!mensaje.startsWith("fi n")); } catch (Exception e) { System.err.print ln(e.getMessage()); System.exit(1); } } } 4/4 Powered by TCPDF (www.tcpdf.org)