Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

problem with sockets C code

Status
Not open for further replies.

neocool

Member level 4
Member level 4
Joined
Jun 3, 2004
Messages
79
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,112
in_class_host

Hello,
I am trying to create a server and a client using c. Using Dev C++ 4.9.8.0 compiler, I cannot compile my code.
First of all, the examples I've found on internet use socket.h, while this version of compier does not have it, just winsock.h
So, I've changed the #include <winsock.h> to my file.

When I compile, it gives me errors like redefinition of "struct in_addr", INADDR_ANY, IN_CLASS_HOST, IN_CLASSA and others.. I don't know where it get's doubles from..

Any help would be appreciated.
Thanks

Here is my code:
--------------------------

#include <string.h>
#include <sys/types.h>
//#include <sys/socket.h>
#include <winsock.h>
#include <netinet/in.h>

#define MYPORT 1026 // connection port for ComBlock

#define BACKLOG 2 // how many pending connections queue will hold

main()
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int sin_size;
int lenof_buf = 8192; //max packet size = 8K
int bytes_received;
void char *buf =[];


sockfd = socket(AF_INET, SOCK_STREAM, 0);
// error checking omitted

my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct

// error checking omitted
sin_size = sizeof(struct sockaddr_in);
bind(sockfd, (struct sockaddr *)&my_addr, &sin_size);

listen(sockfd, BACKLOG);

new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);

bytes_received = recv(new_fd, &buf, lenof_buf, 0);

printf("%c", buf);

}


---------------------------------------
 

Why don't you look at the WinSock examples (available at https://tangentsoft.net/wskfaq/ )

I know winsock is a 'strange' header file. You have to include the Winsock.h file before the Windows.h file (when you're using it too, probably in other header files).
Probably the winsock.h file already defines the structures which are also defined in the socket.h file or an other one included.
I guess you should only include the winsock.h or winsock2.h file.
And check the examples!

Code:
#ifdef WINDOWS_SOCKETS
#include <winsock2.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

Also, don't forget to link to the correct winsock library

Antharax
 

Antharax said:
Why don't you look at the WinSock examples (available at https://tangentsoft.net/wskfaq/ )

I know winsock is a 'strange' header file. You have to include the Winsock.h file before the Windows.h file (when you're using it too, probably in other header files).
Probably the winsock.h file already defines the structures which are also defined in the socket.h file or an other one included.
I guess you should only include the winsock.h or winsock2.h file.
And check the examples!

Code:
#ifdef WINDOWS_SOCKETS
#include <winsock2.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

Also, don't forget to link to the correct winsock library

Antharax


I've fixed all my mistakes with header files.. I am using winsock2.h.
However, how do I link to the correct library? readme file with the example I am using says that I need to link to WSOCK32.LIB.
How do I do it? I had to find the file on the internet and placed it to /include/ and /lib/ folder along with winsock2.h header file..

Here is my compilation log. The help file from Dev-Cpp says that "You probably haven't declared any main() or WinMain() function in your program."
I have a declaration of main()

COMPILE LOG:
Code:
g++.exe "C:\Dev-Cpp\Work\Socks3\server.cpp" -o "C:\Dev-Cpp\Work\Socks3\server.exe"    -I"C:\Dev-Cpp\include\c++"  -I"C:\Dev-Cpp\include\c++\mingw32"  -I"C:\Dev-Cpp\include\c++\backward"  -I"C:\Dev-Cpp\include"   -L"C:\Dev-Cpp\lib"
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0xab):server.cpp: undefined reference to `WSAStartup@8'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0xf3):server.cpp: undefined reference to `WSACleanup@0'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x1dc):server.cpp: undefined reference to `socket@12'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x1ed):server.cpp: undefined reference to `WSAGetLastError@0'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x22d):server.cpp: undefined reference to `htons@4'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x245):server.cpp: undefined reference to `bind@12'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x256):server.cpp: undefined reference to `WSAGetLastError@0'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x27d):server.cpp: undefined reference to `closesocket@4'
C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x2a0):server.cpp: undefined reference to `gethostname@8'

C:\DOCUME~1\admin\LOCALS~1\Temp/cc2nbaaa.o(.text+0x2b1):server.cpp: undefined reference to `WSAGetLastError@0'
 

I was able to add the library to the project.

now the compiled server exe file is supposed to accept port as an argument and display some text that the server is running, but instead it just runs
without even asking me to enter any ports and does not output anything.

any ideas why?
 

since the only code you posted has
main() as main function i guess that you didn't define the arguments?

Code:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  // with argc the number of elements (C-strings) in argv
  while(argc--)
    printf("%s\n", *argv++);
  exit(EXIT_SUCCESS);
}

Don't forget to use the atoi or scanf to convert the ascii port argument to an integer value!

And also don't forget that you cannot start this program with a double click. You should write a .bat file or start it from a command line (cygwin, dos-promt, ...). In Visual C++ you can define arguments in Project/Options/Debug/Arguments. I guess other debuggers will have the same options. ddd has them too.
 

I have solved the problem. It turned out that reinstallation of Dev compiler has helped. Probably I have messed up with the libraries as I was using some that I've found on internet.

Now, I have another question on the same topic.
I want my client to read any file and send it to the server via sockets. I have created a buffer for reading data from some file and define it as "char szBuf[10000]"; I understand that this is not enough for any size of file.
I have tried using "char *szBuf", however after execution, the socket returns errors and does not send anything.
Also, using the first approach with the first case sends a couple (very few) unknown characters.

how would you go around this problem? I am attaching a piece of code form client.cpp file:
Code:
//
	// Send data to the server
	//
	char myfile[] = "datafile.dat";
    char szBuf[10000];    //<----------------
    //char *buffer;             //<------does not work
	FILE *sourceFile;
if ((sourceFile = fopen(myfile, "r")) == NULL){
         printf("Error opening the file\n");
         return; 
    }
    //memset(szBuf, 0, sizeof(szBuf));
 
    nRet = fread(szBuf, 1, 10000, sourceFile); 
    //nRet = fread(buffer, 1, 1000, sourceFile);
 
    //printf("Bytes read from file to szBuf: %d\n", nRet);
    fclose(sourceFile);
    
     //Send szBuf to the socket
   	nRet = send(theSocket,szBuf,strlen(szBuf),0);
	
closesocket(theSocket);
return;
 

//char *buffer; //<------does not work

You are right!!! This cannot work. You just define a pointer to a location in memory. It is not initialized so it points to nothing.
First you have to allocate memory before you can use it ;-).

Code:
buffer = malloc(NR_OF_ITEMS * sizeof(char))

So it's actually the same as allocating a fixed array. You can have more flexibility by chosing the buffer size at runtime (but here it isn't needed)

And why should it matter that the file doesn't fit in the buffer? Just read the buffer untill nRet == 0 (error => probably done with reading). The "file pointer" advanced to the unread part of the file after an fread.

something like
Code:
while ( (nRet = fread(szBuf, 1, 10000, sourceFile) != 0)
  {
    send(theSocket,szBuf,nRet,0); 
  }
fclose(sourceFile); 
closesocket(theSocket);

Antharax
 

THanks Anthrax,
I am trying to implement it right now.

what parameter do I use to open a JPG file for reading and then writing?
is it
sourceFile = fopen(myfile, "rb") <-------- rb for read binary
destinationFile = fopen(saveFile, "ab") <------ ab for append binary?
 

Everything worked. I am able to send any type of file right now! Big thanks!!

I have another question along with hundreds of the other ones.. but one at a time to not to overwhelm anyone here.
The client code right now is using hostname to connect to the server. I want to use IP instead.

I've found some information about converting from host to network order, however having some compilation mistakes.
Here is my current implementation:
Code:
#include <stdio.h>
#include <winsock2.h>
main() definition
{
.
.
.
}

void StreamClient(char *szServer, short nPort)
{.
.
.
	
SOCKADDR_IN saServer;

	saServer.sin_family = AF_INET;
	saServer.sin_port = htons(nPort);	// Port number from command line
	saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
.
.
.}

I was trying to use
saServer.sin_addr.s_addr = inet_addr(szServer);
instead of above stated:
saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);

but when I execute the server, it just cannot connect.

what is wrong in here?
 

Perhaps you should start reading about sockets a bit more ;-)
The msdn has a description about allot of functions of winsock.

https://msdn.microsoft.com/library/...ary/en-us/winsock/winsock/gethostbyname_2.asp

And i would suggest that you buy a good C or C++ book too! If you're writing it on PC, C++ is a good and powerfull language. But it also is a dangerous language. When you do not exactly know what you're doing, you can create strange applications ;-).


about your problem, it is described in the msdn
The gethostbyname function cannot resolve IP address strings passed to it. Such a request is treated exactly as if an unknown host name were passed. Use inet_addr to convert an IP address string the string to an actual IP address, then use another function, gethostbyaddr, to obtain the contents of the hostent structure.

Look at the example code in the entry
https://msdn.microsoft.com/library/...ary/en-us/winsock/winsock/gethostbyaddr_2.asp


A few good links for sockets:
- msdn (see links above)
- https://tangentsoft.net/wskfaq/ (Winsock Faq + example applications)
- https://www.sockets.com/ (a bit of info & examples)

And if you want to go further and write non-blocking clients/servers. Here is a good source of information:
**broken link removed**

Antharax
 

Thank you for the useful information and links. I am in the process of learning, indeed.

I had a question about validity of my way of packetizing data.
The application that I am developing is for the board, that has a small buffer that has to be flushed in order to receive data completely. So, in order to send file through it, I have to first flush the buffer, then send data and flush it again.
On the receiving side, I have to disregard the flushing information.
I am trying to use \0 null characters as the flushing packet. My client just stores everything that goes inbetween.

Would this theoretically work? I am worrying that there might be some intermediate NULL data sent between packets that can make my server disregard the rest of data.

Thank you for suggestion in advance
 

Socket Programming with MFC(2).pdf

WARNING: THE LANGUAGE ON THIS BOARD IS ENGLISH!!! DO NOT UPLOAD OTHER LANGUAGE FILES unless specifically requested and clearly mentionned!!!
 

Would this theoretically work? I am worrying that there might be some intermediate NULL data sent between packets that can make my server disregard the rest of data.

You are right ;-)
Whenever a 0x00 occurs in the data, you got a problem ;-)

you could use a very simple TCP-like packet protocol to send your data:

Code:
+-----+-----+-----+
|START| LEN | CRC |
+-----+-----+-----+
+-----------------+
|      DATA       |
+-----------------+
+-----------+-----+
|  DATA CRC | END |
+-----------+-----+

CRC can be a parity byte or no check at all
Data CRC is optional too
End character is optional too

When you're using TCP, your data should be received correct and in the correct order! That's why a start an a LEN byte should be enough.

Other techniques are possible too (Masking out the Start sequence in the data, ...)

Antharax
 

Thank you Anthrax,

I've decided that I will use one char flag to recognize first, middle and last packets. When trying to send a text file, I take 511 bytes of data and 1 byte for flag, put it into array and send it.
However, for some reason, the text is arriving pretty messy: some of the formatting is lost and possibly there's missing data.
If I am printing out each packet in dos, it looks like my client adds another symbol at the end.. something looking like rombus (any special symbol?). When I take a strlen(Packet), it displays 513 bytes.

I am just using my own computer to test the server and the client at the same time, so I am connecting to myself. I've no idea why the text is getting messed up like that. Before I've introduced the flag to the message, it was arriving fine.

here's how i create a packet from data and a flag:
Code:
char* ConstructPacket(char *Packet, char *Buf, int szBuf, char *flag)
{
    char *newPacket;
    newPacket=(char*)calloc(szBuf+sizeof(char), sizeof(char)); 
    strcat(newPacket, flag); 
    strcat(newPacket, Buf);     
    
    free(Packet);
    
    return (newPacket);
}

I pass the old pointer to packet to clear up some memory. Buf is data from fread(Buf, 1, szBuf, sourceFile), flag is just one character string.

I call the function like this:
Code:
int szPacket = 512;
int szBuf=sizeof(char)*(szPacket-1); //which is 511

Packet = ConstructPacket(Packet, Buf, szBuf, flag);
        
        //Send Buf to the socket
   	    nSent = send(theSocket,Packet,szPacket,0);

I am confused
 

The problem is solved. I was using strcat() function to cancatenate binary data which contained nulls. I've changed it to memcpy().

I haven't mentioned it before because of some problems with the device I am trying to communicate with

Thanks

Thanks
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top