Programar em Socket

13. Re: Programar em Socket

Alex Nunes
allex777

(usa Ubuntu)

Enviado em 19/05/2008 - 12:17h

Pois é esses são os códigos que estou usando para enviar mensagens normais de texto. Agora quero implementar para o cliente enviar arquivo e o servidor receber e ler o arquivo.


  


14. Me ajudem!

Alex Nunes
allex777

(usa Ubuntu)

Enviado em 19/05/2008 - 12:18h

é tipo fazer ações no servidor que o cliente requisita! Acho q é isso!


15. cara

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 13:42h

agora to um poco enrolado, mas se der hj mesmo verifico os arquivos e faço uma alteração para o seu programa transmitir um arquivo. Ai ja posto aqui. Abs


16. Tutorial e Codigos de Socket

Márcio Romeu
marciodfnew

(usa RedHat)

Enviado em 19/05/2008 - 16:49h

Olha ai um tutorial e codigos que achei na net sobre socket, me ajudou muito:

Tutorial ensinando socket:
http://www.dicas-l.com.br/dicas-l/20041219.php

Codigos referidos pelo Alessandro no tutorial:
http://linuxgazette.net/issue74/misc/tougher/

Já passei por esse perrengue de ter que aprender socket no meu trampo, mas não achava nada na net.
Até q fussei tanto e consegui achar, alem do tutorial que achei rapidin, os codigos referidos no tutoria q não estavam completos, o q me fazia ficar doido por não ta entendendo nada.

Bem, espero ter ajudado.



17. Afe Stremer

Eli Carlos
last_evolution

(usa Slackware)

Enviado em 19/05/2008 - 17:22h

"como um código fala mais que mil palavras"

Tu sempre tem uma carta na manga...muleque do capeta...:D

uadshdsuhsddsah

Abraços!


18. ae cara

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 18:49h

hj tive um dia até sossegado então implementei aqui no seu código uma transferencia de arquivos usando uuencode.
Como fiz meio na correria não sei se ta tudo 100%, mas funcionou belezinha. Logico, precisa fazer somente pelo caminho feliz, e ta aceitando no maximo 1Mb de buffer (precisa implementar o buffer dinamico) alem de implementar mais coisas (lógico), mas como fiz no corre ja da pra vc ter uma boa ideia e ver funcionando e melhorar o código.
As rotinas de uuencode baixei da web e dei uma adaptada pois não tinha nenhum código facil aqui.
O resto implementei encima do seu codigo.
Não sei se tem algum estouro de buffer, pois como falei, a ideia foi te mostrar como funciona, pois fiz agora no final do dia.

Primeiro salve o uuencode.h

------ uuencode.h----

/*
* UUEncode/UUDecode
*
* Lib usando somente ANSI C
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/* CRC */
unsigned short CRC = 0x0000;

/* Tabela CRC */
static unsigned short crctab[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};

#define updcrc(cp, crc) ( crctab[((crc>>8)&0x0FF)]^(crc<<8)^(cp&0x0FF) )

/* Encode de char */
char ENC(char ch) {
ch = (ch & 0x03F) + ' ';
switch (ch)
{
case ' ' : ch = 'm';
break;
case '[' : ch = 'd';
break;
case '\\' : ch = 'e';
break;
case ']' : ch = 'f';
break;
case '^' : ch = 'g';
break;
case '\'' : ch = 'h';
break;
}
return(ch);
}

/* Decode de char */
char DECN(char ch) {
switch (ch) {
case 'm' : ch = ' ';
break;
case 'd' : ch = '[';
break;
case 'e' : ch = '\\';
break;
case 'f' : ch = ']';
break;
case 'g' : ch = '^';
break;
case 'h' : ch = '\'';
break;
}
ch = (ch - ' ') & 0x03F;
return(ch);
}

/* Aqui decodificamos 4 chars */
char * outdec (char * p) {
int c1, c2, c3, c4;
char * pret;
char * ret = (char *) malloc(sizeof(char) * 5);
pret = ret;
c1 = *p >> 2;
c2 = (*p << 4) & 0x30 | (p[1] >> 4) & 0x0F;
c3 = (p[1] << 2) & 0x3C | (p[2] >> 6) & 0x03;
c4 = p[2] & 0x3F;

*ret = ENC(c1);
ret++;
*ret = ENC(c2);
ret++;
*ret = ENC(c3);
ret++;
*ret = ENC(c4);
ret++;
*ret = 0;
return pret;
}

/* Aqui decodificamos */
char * outdec2(char * p, char * out, int n) {
int c1, c2, c3;
char * ret;
ret = out;
c1 = DECN(*p) << 2 | DECN(p[1]) >> 4;
c2 = DECN(p[1]) << 4 | DECN(p[2]) >> 2;
c3 = DECN(p[2]) << 6 | DECN(p[3]);
if (n >= 1) { *ret = c1; ret++; *ret = 0; CRC = updcrc(c1,CRC); }
if (n >= 2) { *ret = c2; ret++; *ret = 0; CRC = updcrc(c2,CRC); }
if (n >= 3) { *ret = c3; ret++; *ret = 0; CRC = updcrc(c3,CRC); }
return ret;
}

/* Encode de string */
char * encode(char * in, int size) {
char * out = (char *) malloc((sizeof(char) * size) * 2);
if (out == NULL) {
printf("ERRO na alocacao\n");
exit(-1);
}
char * pout;
char * crcStr;
char * decChar;
char * pdecChar;
char buf[80];
int i, n, cor;

pout = out;
cor = 0;
for (;;) {
n = fr(in, buf, 45, size, cor);
cor += 45;
*pout = ENC(n);
pout++;
for (i = 0; i < n; i++) {
CRC = updcrc(buf[i], CRC);
}
for (i=0; i<n; i += 3) {
decChar = (char *) outdec(&buf[i]);
pdecChar = decChar;
*pout = *decChar; pout++; decChar++;
*pout = *decChar; pout++; decChar++;
*pout = *decChar; pout++; decChar++;
*pout = *decChar; pout++; decChar++;
free(pdecChar);
}
*pout = '\n';
pout++;
*pout = 0;
if (n <= 0) break;
}
crcStr = (char *) malloc(sizeof(char) * 45);
sprintf(crcStr, "CRC= %04X\n", CRC);
strcat(out, crcStr);
strcat(out, "end\n");
return out;
}

/* Decode de string */
int decode(char * in, char * out, int size) {
char * pin;
char * pout;
char buf[80];
char *bp;
int n;
int i;
int tam;
pin = in;
pout = out;

tam = 0;
for (;;) {
for (i = 0; i < 80; i++) {
if (*pin != '\n' && *pin != '\r') {
buf[i] = *pin;
pin++;
} else {
pin++;
buf[i] = 0;
break;
}
}

n = DECN(buf[0]);
if (n <= 0) break;
tam += n;

bp = &buf[1];
while (n > 0) {
pout = outdec2(bp, pout, n);
bp += 4;
n -= 3;
}
}
*pout = 0;
return tam;
}

/* Para leitura de buffer */
int fr(char * fd, char * buf, int cnt, int size, int cor) {
int c, i;
char * pfd = fd;
for (i = 0; i < cor; i++) {
pfd++;
}
for (i = 0; i < cnt; i++) {
c = *pfd;
pfd++;
if ((cor + i + 1) > size) return(i);
buf[i] = c;
}
return (cnt);
}


------ fim uuencode.h----


19. agora o cliente.c

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 18:49h

----- cliente.c -----
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include "uuencode.h"

int main(int argc, char *argv[]) {
int sockdescr;
int numbytesrecv;
struct sockaddr_in sa;
struct hostent *hp;
char buf[BUFSIZ+1];
char *host;
char *dados;
char *arquivo;
FILE * in;
char * conteudoArquivo;
char * pconteudoArquivo;
int tamanhoArquivo;
char c;
char * arquivoEncode;
char * headerEncode;
int tamanhoEncode;

if(argc != 4) {
puts("Uso correto: <cliente> <nome-servidor> <porta> <arquivo>");
exit(1);
}

host = argv[1];
arquivo = argv[3];

if((hp = gethostbyname(host)) == NULL){
puts("Nao consegui obter endereco IP do servidor.");
exit(1);
}

bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;

sa.sin_port = htons(atoi(argv[2]));

if((sockdescr=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
puts("Nao consegui abrir o socket.");
exit(1);
}

printf("numero de bytes %d\n", sizeof sa);
if(connect(sockdescr, (struct sockaddr *) &sa, sizeof sa) < 0) {
puts("Nao consegui conectar ao servidor");
exit(1);
}

// Aqui transmitimos o arquivo
// Primeiro devemos ler e passar o uuencode
if ((in = fopen(arquivo, "rb")) == NULL) {
puts("Nao foi possivel abrir o arquivo");
exit(1);
}

// Agora lemos o arquivo (Vamos ler da forma mais [*****] para ficar claro)
// Depois você pode implementar um buffer mais inteligente
// Vamos também alocar de maneira fixa 1 Mb, não serão aceitos arquivos maiores
// Para isto você deve implementar o realloc ou do jeito que quiser
conteudoArquivo = malloc(sizeof(char) * 1024 * 1024);
pconteudoArquivo = conteudoArquivo;
tamanhoArquivo = 0;
while (!feof(in)) {
c = getc(in);
if (!feof(in)) {
*pconteudoArquivo = c;
pconteudoArquivo++;
tamanhoArquivo++;
}
}
*pconteudoArquivo = 0;
fclose(in);

// Faz o uuencode
headerEncode = (char *) malloc(sizeof(char) * 1024);
sprintf(headerEncode, "...begin... 777 %s\n", arquivo);
arquivoEncode = encode(conteudoArquivo, tamanhoArquivo);
tamanhoEncode = strlen(arquivoEncode) + strlen(headerEncode);

// Vamos montar um (mini header)
dados = (char *) malloc(sizeof(char) * 1024);
sprintf(dados, "ARQUIVO: [%s] - TAMANHO: [%d]\n\n", arquivo, tamanhoEncode);

if(write(sockdescr, dados, strlen(dados)) != strlen(dados)){
puts("Nao consegui mandar os dados");
exit(1);
}

// Agora vamos mandar o arquivo
if(write(sockdescr, headerEncode, strlen(headerEncode)) != strlen(headerEncode)){
puts("Nao consegui mandar o headerEncode");
exit(1);
}
if(write(sockdescr, arquivoEncode, strlen(arquivoEncode)) != strlen(arquivoEncode)){
puts("Nao consegui mandar o arquivoEncode");
exit(1);
}

// Nao vamos considerar a conversa toda por enquanto
//read(sockdescr, buf, BUFSIZ);
//printf("Sou o cliente, recebi: %s\n", buf);

close(sockdescr);

// Limpamos da memoria
free(conteudoArquivo);
free(arquivoEncode);
exit(0);
}
---- fim cliente.c ---


20. e o servidor.c

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 18:50h

----- servidor.c ----
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include "uuencode.h"

#define TAMFILA 5
#define MAXHOSTNAME 30

int main (int argc, char *argv[]) {

int s, t;
unsigned int i;
char buf [BUFSIZ + 1];
struct sockaddr_in sa, isa;
struct hostent *hp;
char localhost [MAXHOSTNAME];
char * conteudoArquivo;
int bufLido = 0;
int bufTotal = 0;

signal();
if (argc != 2) {
puts("Uso correto: servidor <porta>");
exit(1);
}

gethostname (localhost, MAXHOSTNAME);
if ((hp = gethostbyname( localhost)) == NULL){
puts ("Nao consegui meu proprio IP");
exit (1);
}

sa.sin_port = htons(atoi(argv[1]));
sa.sin_family = hp->h_addrtype;
bcopy ((char *) hp->h_addr, (char *) &sa.sin_addr, hp->h_length);

if ((s = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0){
puts ("Nao consegui abrir o socket");
exit ( 1 );
}

if (bind(s, (struct sockaddr *) &sa,sizeof(sa)) < 0){
puts ("Nao consegui fazer o bind");
exit ( 1 );
}
listen (s, TAMFILA);

while (1){
i = sizeof(sa);
if ((t=accept(s, (struct sockaddr *) &isa,&i))<0){
puts ("Nao consegui fazer conexao");
exit (1);
}
read(t, buf, BUFSIZ);

// Vamos somente considerar o caminho feliz e que aqui veio todo o arquivo
printf("Sou o servidor, recebi a mensagem----> %s\n", buf);
// Precisamos ler o buffer total e o nome do arquivo
char * posBufIni = strstr(buf, "TAMANHO: [");
if (posBufIni == NULL) {
printf("Erro ao ler caminho feliz 1.\n");
exit(-1);
}
char * posBufFim = strstr(posBufIni + 10, "]");
if (posBufFim == NULL) {
printf("Erro ao ler caminho feliz 2.\n");
exit(-1);
}
char * tamStr = (char *) malloc(sizeof(char) * 1024);
if (tamStr == NULL) {
printf("Falta de memoria.\n");
exit(-1);
}
int tamanhoDados = strlen(posBufIni) - strlen(posBufFim) - 10;
strncpy(tamStr, posBufIni + 10, tamanhoDados);
tamStr[tamanhoDados] = 0;
bufTotal = atoi(tamStr);
printf("Buffer Total: %d\n", bufTotal);

conteudoArquivo = malloc(sizeof(char) * 1024 * 1024);
*conteudoArquivo = 0;
memset(buf, 0x00, BUFSIZ + 1);
read(t, buf, BUFSIZ);
strcpy(conteudoArquivo, buf);
bufLido = strlen(conteudoArquivo);
int mode;
char dest[128];
sscanf(conteudoArquivo, "...begin... %o %s", &mode, dest);
bufTotal = bufTotal - strlen(conteudoArquivo);
strcpy(conteudoArquivo, "");
while (bufLido < bufTotal) {
memset(buf, 0x00, BUFSIZ + 1);
read(t, buf, BUFSIZ);
strcat(conteudoArquivo, buf);
bufLido = strlen(conteudoArquivo);
}

// Agora devemos gravar o conteudo
conteudoArquivo[bufTotal] = 0;
FILE * fout;
fout = fopen(dest, "wb");
if (fout == NULL) {
printf("Erro ao criar arquivo: %s\n", dest);
exit(4);
}

char * out = (char *) malloc((sizeof(char) * bufTotal) * 2);
int tam2 = decode(conteudoArquivo, out, bufTotal);
for (i = 0; i < tam2; i++) {
putc(out[i], fout);
}
fclose(fout);
printf("Gerou arquivo: %s\n", dest);

//Nao vamos devolver nada por enquanto
write(t,"OK\n", 3);
close(t);
}

}
----- fim servidor.c ----


21. ae

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 18:57h

testei aqui e o vol não zuou nada.
Para compilar, crie 2 diretórios (para ter certeza do envio do arquivo) e então copie o uuencode.h em ambos e compile com gcc.
Depois inicie o servidor por ex:
( O bind precisa de root )
# sudo ./servidor 666
Depois copie um arquivo zip ou qualquer outro para o diretorio do cliente.
Então:
# ./cliente localhost 666 arquivo.zip

O servidor deverá receber o arquivo.
Depois entre no diretório do servidor e:
# file arquivo.zip
Vera que é um zip de verdade.
Então pode lidar com o arquivo.

Enfim, o repito, como código vale mais que mil palavras, só olhar o código, ver como funciona e modificar ao seu gosto.

Espero que ajude!

ABS


22. Agradecimento!

Alex Nunes
allex777

(usa Ubuntu)

Enviado em 21/05/2008 - 13:07h

Valeu stremer. Muito obrigado! Vou compilar sim to sem muyito tempo por isso demorei a postar. Assim que compilar vou te responder. Mas obrigado mesmo!


23. Alguém sabe!

Alex Nunes
allex777

(usa Ubuntu)

Enviado em 26/05/2008 - 17:58h

comunicação entre dois programas em C (servidor - cliente), para a troca de strings.


24. Valeu!

Alex Nunes
allex777

(usa Ubuntu)

Enviado em 26/05/2008 - 18:14h

Funcionou stremer. Blz! Vou dar uma estuda para ver se aprendo mais. Muito obrigado pela ajuda!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts