Avatar billede stuffedk Nybegynder
27. januar 2008 - 20:10 Der er 11 kommentarer og
1 løsning

TCP forbindelse

Hej eksperter.
Jeg er gået lidt i gang med at lære c++ og vil gerne vide hvordan man laver en netværksforbindelse (på win xp). Det kunne være rart med et eksempel. Er der ikke nogen der har et meget simpelt (så kort som muligt) eksempel med f.eks. en client konsol der kan sende beskeder til en server konsol, eller noget lignende?
Håber nogen kan hjælpe.
Avatar billede arne_v Ekspert
27. januar 2008 - 20:32 #1
Eksempel med rå winsock interface:

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

#include <windows.h>
#include <errno.h>

void get(char *hostname,int port,char *path, char *fnm)
{
  FILE *fp;
  int sd,status,len,first,tmp;
  char cmd[512],resp[51200],*body;
  struct sockaddr local,remote;
  struct hostent *hostinfo;
  /* create socket */
  sd=socket(AF_INET,SOCK_STREAM,0);
  if(sd<0) {
      printf("Error creating socket: %s\n",strerror(errno));
      goto fin;
  }
  /* bind socket */
  local.sa_family=AF_INET;
  memset(local.sa_data,0,sizeof(local.sa_data));
  status=bind(sd,&local,sizeof(local));
  if(status<0) {
      printf("Error binding socket: %s\n",strerror(errno));
      goto fin;
  }
  /* lookup host */
  hostinfo=gethostbyname(hostname);
  if(!hostinfo) {
      printf("Error looking up host: %s\n",hostname);
      goto fin;
  }
  /* connect to host */
  remote.sa_family=hostinfo->h_addrtype;
  memcpy(remote.sa_data+2,hostinfo->h_addr_list[0],hostinfo->h_length);
  *((short *)remote.sa_data)=port;
  tmp=remote.sa_data[0];
  remote.sa_data[0]=remote.sa_data[1];
  remote.sa_data[1]=tmp;
  status=connect(sd,&remote,sizeof(remote));
  if(status!=0) {
      printf("Error connecting to host: %s port: %d\n",hostname,port);
      goto fin;
  }
  /* send GET request */
  sprintf(cmd,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",path,hostname);
  status=send(sd,cmd,strlen(cmd),0);
  if(status<0) {
      printf("Error sending GET request\n");
      goto fin;
  }
  /* read response */
  fp = fopen(fnm,"wb");
  first = 1;
  while ((len=recv(sd,resp,sizeof(resp),0))>0) {
      if(first) {
          body = strstr(resp,"\r\n\r\n") + 4;
          first = 0;
      } else {
          body = resp;
      }
      fwrite(body,len-(body-resp),1,fp);
  }
  fclose(fp);
fin:
  closesocket(sd);
  return;
}

int main(int argc,char *argv[])
{
  WSADATA WSAData;
  WSAStartup(0x0101,&WSAData);
  get("www.eksperten.dk",80,"/img/elogo.png","elogo.png");
  WSACleanup();
  return 0;
}
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:01 #2
hmm kan ikke compile det der med Dev-C++.

Jeg får disse errors:
[Linker error] undefined reference to `socket@12'
[Linker error] undefined reference to `bind@12'
[Linker error] undefined reference to `gethostbyname@4'
  [Linker error] undefined reference to `connect@12'
Avatar billede arne_v Ekspert
27. januar 2008 - 21:03 #3
Command line skal man angive:

-lws2_32

I dev-cpp skal du ind i link options og angive noget tilsvarende.
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:03 #4
med MS Visual 6.0 får jeg disse errors

--------------------Configuration: Cpp1 - Win32 Debug--------------------
Linking...
Cpp1.obj : error LNK2001: unresolved external symbol _closesocket@4
Cpp1.obj : error LNK2001: unresolved external symbol _recv@16
Cpp1.obj : error LNK2001: unresolved external symbol _send@16
Cpp1.obj : error LNK2001: unresolved external symbol _connect@12
Cpp1.obj : error LNK2001: unresolved external symbol _gethostbyname@4
Cpp1.obj : error LNK2001: unresolved external symbol _bind@12
Cpp1.obj : error LNK2001: unresolved external symbol _socket@12
Cpp1.obj : error LNK2001: unresolved external symbol _WSACleanup@0
Cpp1.obj : error LNK2001: unresolved external symbol _WSAStartup@8
Debug/Cpp1.exe : fatal error LNK1120: 9 unresolved externals
Error executing link.exe.

Cpp1.exe - 10 error(s), 0 warning(s)
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:04 #5
ok prøver lige
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:15 #6
ok det rettede fejlen. men hvor er resultatet? er det den variabel der hedder "body" eller?
Avatar billede arne_v Ekspert
27. januar 2008 - 21:18 #7
Hvis du kigger lidt på funktionen:

void get(char *hostname,int port,char *path, char *fnm)

og kaldet:

get("www.eksperten.dk",80,"/img/elogo.png","elogo.png");

så burde det fremgå at den henter http://wwww.ekspereten.dk:80/img/elogp.png og
gemmer den i en fil elogo.png
Avatar billede arne_v Ekspert
27. januar 2008 - 21:19 #8
Det var bare et eksempel på socket programmering. Der er mange andre måder at bruge
det på, men at hente en fil med HTTP er sådan noget der er nemt at forholde sig til.
Avatar billede arne_v Ekspert
27. januar 2008 - 21:25 #9
server eksempel:

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

#include <windows.h>
#include <errno.h>

int main(int argc,char *argv[])
{
  WSADATA WSAData;
  int sd,sd2,status,len,ix;
  char cmd[100],*p;
  struct sockaddr_in local;
  /* windows specifik */
  WSAStartup(0x0101,&WSAData);
  /* create socket */
  sd=socket(AF_INET,SOCK_STREAM,0);
  if(sd<0)
  {
      printf("Error creating socket: %s\n",strerror(errno));
      goto fin;
  }
  /* bind socket */
  local.sin_family=AF_INET;
  local.sin_port = htons(1234);
  local.sin_addr.s_addr = INADDR_ANY;
  status=bind(sd,(struct sockaddr *)&local,sizeof(local));
  if(status<0)
  {
      printf("Error binding socket: %s\n",strerror(errno));
      goto fin;
  }
  /* listen socket */
  status=listen(sd,5);
  if(status<0)
  {
      printf("Error listening socket: %s\n",strerror(errno));
      goto fin;
  }
  /* accept connection */
  sd2=accept(sd,0,0);
  if(sd2<0)
  {
      printf("Error accepting socket: %s\n",strerror(errno));
      goto fin;
  }
  /* read data */
  p=(char *)&cmd;
  ix=0;
  while((len=recv(sd2,p+ix,1,0))>0)
  {
    ix=ix+len;
    if(cmd[ix-1]=='\n')
    {
        cmd[ix-1]='\0';
        printf("CMD: %s\n",cmd);
        ix=0;
    }
  }
fin:
  /* close sockets */
  closesocket(sd2);
  closesocket(sd);
  /* windows specifik */
  WSACleanup();
  return 0;
}

Bemærk at testet if(cmd[ix-1]=='\n') er lidt uldent, men igen det viser da hvordan
man accepter en connection.
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:27 #10
ahh selvfølgelig. jeg havde godt set urlen, men kunne ikke lige se hvor den gjorde af "resultatet". nu har jeg noget at lege lidt med, tak for det. C minder faktisk en del om PHP. Kan du forklare det med "-lws2_32" lidt? Og er der noget du vil andbefale en begynder at læse? (har lavet lidt tutorials). Og den sidste ting, smid et svar, så du kan få points :)
Avatar billede arne_v Ekspert
27. januar 2008 - 21:32 #11
PHP er en del inspireret af C (det er der mange andre sprog som også er).

-lws2_32 betyder at man skal linke med libws2_32.a som indeholder de funktioner der
ellers manglede.

Har du en bog om C ?

Ellers med hensyn til net programmering, så søg på "socket programming" på Google - der
masser af hits.

Der er også andre måder at lave netværks programmering på (INET, MFC, .NET etc.), men
en fordel ved de rå sockets er at koden er nem at portere til Linux/Unix.

Og et svar.
Avatar billede stuffedk Nybegynder
27. januar 2008 - 21:49 #12
Tak for det.
Jeg har ingen bøger om emnet, men det kunne være jeg skulle gå på biblioteket en af dagene.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester