Avatar billede stigc Nybegynder
12. april 2004 - 17:52 Der er 17 kommentarer og
2 løsninger

winsock med C

Følgende intialisere sockets i et C++ program

#include <windows.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdio.h"

using namespace std;
WSAData wData;
if (WSAStartup(MAKEWORD(1,1), &wData) == SOCKET_ERROR) return 1;

jeg prøver at lave det samme i et C program, men C kender ikke til namespaces, og jeg kan derfor ikke bruge using. Hvordan bruger jeg så WSAData og WSAStartup i C?
Avatar billede driis Nybegynder
12. april 2004 - 18:01 #1
using namespace std;

Skulle ikke være nødvendigt for at bruge WSAData eller WSAStartup. Det skal bruges for at tilgå std namespacet som defineres når du inkluderer stdlib.h eller stdio.h
Avatar billede driis Nybegynder
12. april 2004 - 18:07 #2
Følgende fungerer i C:

WSADATA wData;
if (WSAStartup(MAKEWORD(1,1), &wData) == SOCKET_ERROR)
  return 1;

WSADATA skal altså være med stort.
Avatar billede driis Nybegynder
12. april 2004 - 18:09 #3
Mere korrekt:
struct WSAData wData;
if (WSAStartup(MAKEWORD(1,1), &wData) == SOCKET_ERROR)
    return 1;

I C skal du bruge struct keywordet for at erklære en struct.
Avatar billede stigc Nybegynder
12. april 2004 - 18:43 #4
Du har jo ret. Jeg husker det bare som der jeg havde problemer. Nu prøvede jeg igen

hostent *h1 = gethostbyname("www.sdfgdfg.dk");

Den kender ikke "hostent"
Avatar billede arne_v Ekspert
12. april 2004 - 19:01 #5
struct hostent *h1 = ...
Avatar billede arne_v Ekspert
12. april 2004 - 19:02 #6
I C skal man nævne struct medmindre der er en typedef på navnet.
Avatar billede stigc Nybegynder
12. april 2004 - 19:03 #7
Det skriver i jo også! :)
Avatar billede arne_v Ekspert
12. april 2004 - 19:07 #8
Og for en god ordens skyld: stdio.h/stdlib.h eller cstdio/cstdlib kræver
ikke using namespace std - iostream etc. gør.
Avatar billede stigc Nybegynder
12. april 2004 - 19:20 #9
Følgende kan jeg ikke oversætte til c:

  hostent *h1 = gethostbyname("xxxxx.dk");
  char* address = inet_ntoa(*(reinterpret_cast<in_addr*>(h1->h_addr)));

har prøvet med

  struct hostent *hptr = gethostbyname("xxxxx.dk");
  memcpy(hptr->h_addr_list[0], &sad.sin_addr.s_addr, sizeof(sad.sin_addr.s_addr));

men det returnerer -1 når jeg connector.
Avatar billede arne_v Ekspert
12. april 2004 - 19:24 #10
Jeg tror at du kopierer den forkerte vej.
Avatar billede arne_v Ekspert
12. april 2004 - 19:24 #11
Jeg bruger:

  hostinfo=gethostbyname(hostname);
  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;
Avatar billede stigc Nybegynder
12. april 2004 - 19:25 #12
Det gjorde jeg jo også. Flot. Læg et svar og jeg deler ud.
Avatar billede arne_v Ekspert
12. april 2004 - 19:25 #13
int port;
  int tmp;
  struct sockaddr remote;
  struct hostent *hostinfo;
Avatar billede arne_v Ekspert
12. april 2004 - 19:27 #14
ok
Avatar billede stigc Nybegynder
12. april 2004 - 21:02 #15
Ved i hvordan man laver non-blocking kald med recv, eller endnu bedre et kald med en bestemt timeout?

recv(sd, buf, sizeof(buf), 0);
Avatar billede arne_v Ekspert
12. april 2004 - 21:11 #16
Prøv og kig på dette eksempel (som jeg har postet før):

#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,int noblock)
{
  int sd,status,len,ix,tmp;
  char cmd[512],resp[51200];
  struct sockaddr local,remote;
  struct hostent *hostinfo;
  time_t t;
  int one = 1;
  /* 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\n\r\n",path,hostname);
  status=send(sd,cmd,strlen(cmd),0);
  if(status<0) {
      printf("Error sending POST request\n");
      goto fin;
  }
  /* read response */
  ix=0;
  if(noblock) {
      status=ioctlsocket(sd, FIONBIO, &one);
      if(status<0) {
        printf("Error setting socket nonblocked: %s\n",strerror(errno));
        goto fin;
      }
      t=time(NULL);
      while (time(NULL)<(t+10)) {
        len=recv(sd,resp+ix,sizeof(resp)-ix-1,0);
        if(len<0) len=0;
        ix = ix + len;
        printf("no blocking read %d bytes\n",len);
        Sleep(1000);
      }
  } else {
      while ((len=recv(sd,resp+ix,sizeof(resp)-ix-1,0))>0) {
        ix = ix + len;
        printf("blocking read %d bytes\n",len);
      }
  }
  resp[ix]='\0';
  /*printf("%s",resp);*/
fin:
  closesocket(sd);
  return;
}

int main(int argc,char *argv[])
{
  WSADATA WSAData;
  WSAStartup(0x0101,&WSAData);
  get("www.dr.dk",80,"/",0);
  get("www.dr.dk",80,"/",1);
  WSACleanup();
}
Avatar billede stigc Nybegynder
12. april 2004 - 21:51 #17
Med

ioctlsocket(sd, FIONBIO, &one);

returnere min connect pludselig -1. Før connected den fint.
Avatar billede arne_v Ekspert
12. april 2004 - 21:55 #18
Jeg kalder ioctlsocket efter connect !

Måske gør det en forskel ?
Avatar billede stigc Nybegynder
12. april 2004 - 22:08 #19
Det gør det.
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