to create a socket to read image from url in linux - sockets

I want to write a socket program which read an image from an url and store it at a location.
I am familiar with basic of socket programming but never created such type of socket.
Below is the code to create a socket to read data from client which i want to modify for above mentioned problem.
Please help me with this.
Thank you
Code::
include<stdio.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<errno.h>
#include<stdlib.h>
#define sport 5000
int main(int argc,char **argv[])//Main function
{
struct sockaddr_in serveraddr;
int m,sd,acceptsd,rc,i;
char command[]="hello\n";
if((sd=socket(AF_INET,SOCK_STREAM,0))<0)
{
perror("error in socket creation\n");
exit(0);
}
memset(&serveraddr,0,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(sport);
serveraddr.sin_addr.s_addr=(INADDR_ANY);
//serveraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
rc=bind(sd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
if(rc<0)
{
perror("srver bind error\n");
close(sd);
exit(-1);
}
rc=listen(sd,5);
if(rc<0)
{
perror("listen error");
close(sd);
exit(-1);
}
printf("server is ready to accept connection\n");
printf("\n");
acceptsd=accept(sd,NULL,NULL);
if(acceptsd<0)
{
perror("error in accepting\n");
exit(-1);
close(sd);
}
rc=send(acceptsd,command2,sizeof(command2),0);
if(rc<0)
{
perror("error in sending\n");
close(acceptsd);
close(sd);
exit(-1);
}
close(acceptsd);
close(sd);
exit(0);
}

The code needs to use TCP sockets and implement HTTP protocol to be able to access any URLs.
Implementing HTTP protocol handling on your own is a daunting and labour intensive task. A good start would be using libcurl.

Related

how can I read and unpack a protobuf c packed message in server side(using sockets)

I,m totally new in protobuf-c
I,m trying to create a socket connection and send protobuf packed message over the socket using c language
I packed the message within client code and send it to the server.But the server failed to receive the packed data and unpack it
my client code is
client.c
void *clientThread(void *arg)
{
Messages t_message = MESSAGES__INIT;
//while(1)
{
void *buf;
unsigned len;
int32_t s32_send_status;
t_message.name="anu";
len=messages__get_packed_size(&t_message);
buf=malloc(len);
messages__pack(&t_message,buf);
s32_send_status=send(gs32_clientSocket ,buf,len,0);
//s32_send_status=send(gs32_clientSocket ,(unsigned char *)
//(&t_message),sizeof(t_message) ,0);
if(s32_send_status>0){
printf("data send to server.\n");
}
else{
printf("failed to send data to server\n");
And my server code is
server.c
void *socketThread(void *arg)
{
Messages *t_message;
uint8_t buf[1024];
int32_t len;
// unsigned length;
//while(1)
{
gs32_valread = read( gs32_new_socket,buf,len);
if(gs32_valread==0){
printf("disconnected\n");
exit(1);
}
else if(gs32_valread<0){
printf("error\n");
exit(1);
}
else{
t_message = messages__unpack(NULL,len,buf);
printf("name=%s\n",t_message->name);
messages__free_unpacked(t_message,NULL);
}
sleep(1);
close(gs32_new_socket);
}
return NULL;
}
if my packing is correct how can I unpack it in the server side.
If anybody know this answer please help me to solve it.Thank you

TCP simple client for a robot server. Not sending data

I am writing a simple TCP client so that I can connect to an UR (Universal Robot) robot, and send messages (popup XXXX) to the port number 29999, to generate popup messages in the UR screen. UR server does not respond correctly to the gethostbyaddr neither gethostbyname functions when connecting, so, for testing, I connect directly to the IP and Port. The code of the simple TCP client is as follows:
int initTCPSocket(void)
{
struct in_addr ip;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("ERROR opening socket");
return -1;
}
portno = atoi(serverPort.c_str());
if (!inet_aton(serverIP.c_str(), &ip))
printf(" ERROR: error parsing IP address %s", serverIP.c_str());
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htons(ip.s_addr);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
printf("ERROR connecting to server");
return -3;
}
else
printf("Connected to server");
}
The code that actually sends data is:
bool SendDataTCP (tekniker_tcp_comms::SendDataTCP::Request &req, tekniker_tcp_comms::SendDataTCP::Response &res)
{
if (sockfd < 0)
{
ROS_INFO("ERROR in connection");
res.dataSent=false;
return true;
}
size_t msgLength = req.msg.data.length();
//write to connected server.
int n = write(sockfd, req.msg.data.c_str(),(int)msgLength);
if (n < 0)
{
ROS_INFO("ERROR writing to socket");
res.dataSent=false;
}
else
{
ROS_INFO("write %d bytes. Message %s",n, req.msg.data.c_str());
res.dataSent=true;
}
return true;
}
I obtain messages of correct connection, and I can call the Service, and the write function works ok, but, no popup appears in the UR. It seems the UR does not receive correctly the messages.
Connecting to the UR server for popup messages using ncat ( ncat 172.16.205.2 29999) and sending messages manually works fine.
After debugging for some hours, I can not find any cause for this problem. I would appreciate a lot any kind of advise,
Thank you in advance,
After inserting Wireshark to monitor TCP/IP, the problem was with the LF termination character, that was not correctly sent.
Solving this problem the client has worked correctly.

Not able to receive File name in server sent by client

I am trying to write a simple socket program which reads a file name in client and sends it to the server. The contents of file are sent to the Client back if present. The client and server are able to successfully able to connect but when I read a file name I don't get any output(program doesn't terminates). Please tell me what is going wrong.
server.c
int main()
{
int create_socket,new_socket,fd,addlen,n;
int bufsize=1024;
char *buffer=malloc(bufsize);
char fname[255];
struct sockaddr_in address;
//printf("program");
if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0)
printf("socket created");
address.sin_family=AF_INET;
address.sin_port=htons(15000);
address.sin_addr.s_addr=INADDR_ANY;
if(bind(create_socket,(struct sockaddr*)&address,sizeof(address))==0)
printf("socket binded");
while(1)
{
printf("Inside while loop");
listen(create_socket,3);
addlen=sizeof(struct sockaddr_in);
if(new_socket=accept(create_socket,(struct sockaddr*)&address,&addlen)>0)
printf("%d connected",inet_ntoa(address.sin_addr));
else
printf("not connected");
recv(new_socket,fname,255,0);
printf("file name is %s",fname);
if(fd=open(fname,O_RDONLY)<0)
{
strcpy(buffer,"Not such file found");
send(new_socket,buffer,sizeof(buffer),0);
}
else
{
while(n=read(fd,buffer,bufsize)>0)
send(new_socket,buffer,n,0);
}
close(new_socket);
}
close(create_socket);
}
client.c
int main(int argc,char *argv[])
{
int create_socket,n;
int bufsize=1024;
char *buffer=malloc(bufsize);
char fname[255];
struct sockaddr_in address;
if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0)
printf("socket created\n");
address.sin_family=AF_INET;
address.sin_port=htons(15000);
inet_pton(AF_INET,argv[1],&address.sin_addr);
if(connect(create_socket,(struct sockaddr*)&address,sizeof(address))==0)
printf("%s connected\n",argv[1]);
else
printf("not connected\n");
printf("Enter the filename\n");
scanf("%s",fname);
send(create_socket,fname,strlen(fname),0);
printf("get the values");
while(n=recv(create_socket,buffer,bufsize,0)>0)
write(1,buffer,n);
return close(create_socket);
}
With the information provided, two problems with transmitting the file name are apparent:
(1) You do not check the return value of send. You cannot be sure what is sent.
(2) You choose not to send the terminating '\0' over the network. Therefore, the receiver has no way of determining when the complete file name has been received. The receiver also does not check the return value of recv. Additionally, the receiver does not bother to terminate the received filename with a '\0'.

WSAConnect returns WSAEINVAL on WindowsXP

I use sockets in non-blocking mode, and sometimes WSAConnect function returns WSAEINVAL error.
I investigate a problem and found, that it occurs if there is no pause (or it is very small ) between
WSAConnect function calls.
Does anyone know how to avoid this situation?
Below you can found source code, that reproduce the problem. If I increase value of parameter in Sleep function to 50 or great - problem dissapear.
P.S. This problem reproduces only on Windows XP, on Win7 it works well.
#undef UNICODE
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
static int getError(SOCKET sock)
{
DWORD error = WSAGetLastError();
return error;
}
void main()
{
SOCKET sock;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
fprintf(stderr, "Socket Initialization Error. Program aborted\n");
return;
}
for (int i = 0; i < 1000; ++i) {
struct addrinfo hints;
struct addrinfo *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
if (0 != getaddrinfo("172.20.1.59", "8091", &hints, &res)) {
fprintf(stderr, "GetAddrInfo Error. Program aborted\n");
closesocket(sock);
WSACleanup();
return;
}
struct addrinfo *ptr = 0;
for (ptr=res; ptr != NULL ;ptr=ptr->ai_next) {
sock = WSASocket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, NULL); //
if (sock == INVALID_SOCKET)
int err = getError(sock);
else {
u_long noblock = 1;
if (ioctlsocket(sock, FIONBIO, &noblock) == SOCKET_ERROR) {
int err = getError(sock);
closesocket(sock);
sock = INVALID_SOCKET;
}
break;
}
}
int ret;
do {
ret = WSAConnect(sock, ptr->ai_addr, (int)ptr->ai_addrlen, NULL, NULL, NULL, NULL);
if (ret == SOCKET_ERROR) {
int error = getError(sock);
if (error == WSAEWOULDBLOCK) {
Sleep(5);
continue;
}
else if (error == WSAEISCONN) {
fprintf(stderr, "+");
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
else if (error == 10037) {
fprintf(stderr, "-");
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
else {
fprintf(stderr, "Connect Error. [%d]\n", error);
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
}
else {
int one = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one));
fprintf(stderr, "OK\n");
break;
}
}
while (1);
}
std::cout<<"end";
char ch;
std::cin >> ch;
}
You've got a whole basketful of errors and questionable design and coding decisions here. I'm going to have to break them up into two groups:
Outright Errors
I expect if you fix all of the items in this section, your symptom will disappear, but I wouldn't want to speculate about which one is the critical fix:
Calling connect() in a loop on a single socket is simply wrong.
If you mean to establish a connection, drop it, and reestablish it 1000 times, you need to call closesocket() at the end of each loop, then call socket() again to get a fresh socket. You can't keep re-connecting the same socket. Think of it like a power plug: if you want to plug it in twice, you have to unplug (closesocket()) between times.
If instead you mean to establish 1000 simultaneous connections, you need to allocate a new socket with socket() on each iteration, connect() it, then go back around again to get another socket. It's basically the same loop as for the previous case, except without the closesocket() call.
Beware that since XP is a client version of Windows, it's not optimized for handling thousands of simultaneous sockets.
Calling connect() again is not the correct response to WSAEWOULDBLOCK:
if (error == WSAEWOULDBLOCK) {
Sleep(5);
continue; /// WRONG!
}
That continue code effectively commits the same error as above, but worse, if you only fix the previous error and leave this, this usage will then make your code start leaking sockets.
WSAEWOULDBLOCK is not an error. All it means after a connect() on a nonblcoking socket is that the connection didn't get established immediately. The stack will notify your program when it does.
You get that notification by calling one of select(), WSAEventSelect(), or WSAAsyncSelect(). If you use select(), the socket will be marked writable when the connection gets established. With the other two, you will get an FD_CONNECT event when the connection gets established.
Which of these three APIs to call depends on why you want nonblocking sockets in the first place, and what the rest of the program will look like. What I see so far doesn't need nonblocking sockets at all, but I suppose you have some future plan that will inform your decision. I've written an article, Which I/O Strategy Should I Use (part of the Winsock Programmers' FAQ) which will help you decide which of these options to use; it may instead guide you to another option entirely.
You shouldn't use AI_PASSIVE and connect() on the same socket. Your use of AI_PASSIVE with getaddrinfo() tells the stack you intend to use this socket to accept incoming connections. Then you go and use that socket to make an outgoing connection.
You've basically lied to the stack here. Computers find ways to get revenge when you lie to them.
Sleep() is never the right way to fix problems with Winsock. There are built-in delays within the stack that your program can see, such as TIME_WAIT and the Nagle algorithm, but Sleep() is not the right way to cope with these, either.
Questionable Coding/Design Decisions
This section is for things I don't expect to make your symptom go away, but you should consider fixing them anyway:
The main reason to use getaddrinfo() — as opposed to older, simpler functions like inet_addr() — is if you have to support IPv6. That kind of conflicts with your wish to support XP, since XP's IPv6 stack wasn't nearly as heavily tested during the time XP was the current version of Windows as its IPv4 stack. I would expect XP's IPv6 stack to still have bugs as a result, even if you've got all the patches installed.
If you don't really need IPv6 support, doing it the old way might make your symptoms disappear. You might end up needing an IPv4-only build for XP.
This code:
for (int i = 0; i < 1000; ++i) {
// ...
if (0 != getaddrinfo("172.20.1.59", "8091", &hints, &res)) {
...is inefficient. There is no reason you need to keep reinitializing res on each loop.
Even if there is some reason I'm not seeing, you're leaking memory by not calling freeaddrinfo() on res.
You should initialize this data structure once before you enter the loop, then reuse it on each iteration.
else if (error == 10037) {
Why aren't you using WSAEALREADY here?
You don't need to use WSAConnect() here. You're using the 3-argument subset that Winsock shares with BSD sockets. You might as well use connect() here instead.
There's no sense making your code any more complex than it has to be.
Why aren't you using a switch statement for this?
if (error == WSAEWOULDBLOCK) {
// ...
}
else if (error == WSAEISCONN) {
// ...
}
// etc.
You shouldn't disable the Nagle algorithm:
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ...);

TCP Client with select , after connect waits for input

I've ran into a problem with a simple TCP Client implemented using select.
The problem is that,at the second printf it only displays before it gets to the connect() function then waits for user input. Does connect block the rest of the program until i send something? (The TCP server is also implemented using select but i didn't find anything wrong with it)
I've searched on the web and couldn't find a cause or maybe i didn't search for the right thing..
#include <includes.h>
int main()
{
int sfd;
fd_set rset;
char buff[1024]=" ";
char playerName[20]="";
int nameSet=0;
struct sockaddr_in server;
sfd= socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{ printf("socket not created\n"); return 0; }
bzero(&server,sizeof(struct sockaddr_in));
server.sin_family=AF_INET;
server.sin_port=htons(2020);
inet_aton("127.0.0.1",&server.sin_addr);
//here is the problem after %d which calls the connect() function
printf("Conexion returned:%d \n Name:",connect(sfd,(struct sockaddr *)&server,sizeof(server)));
for(;;)
{
bzero(buff,1024);
FD_ZERO(&rset);
FD_SET(0,&rset);
FD_SET(sfd,&rset);
if(select(sfd+1,&rset,NULL,NULL,NULL)<0)
{
printf("con-lost!\n");
break;
}
if(FD_ISSET(0,&rset))
{
printf("Talk: \n");
scanf("%s",buff);
if(nameSet==0)
{
strcpy(playerName,buff);
nameSet=1;
printf("Hi:%s\n",playerName);
}
if(write(sfd,buff,strlen(buff)+10)<0)
{
break;
}
}
if(FD_ISSET(sfd,&rset)>0)
{
if(read(sfd,buff,1024)<=0)
{
printf("con is off!\n");
break;
}
printf("msg rcd %s\n",buff);
}
} //endfor
close(sfd);
return 0;
} //endmain
The connect function, on a blocking socket, blocks until the connect operation succeeds or fails.
You should be warned that using select with a blocking socket, which is what your program does, does not ensure that your program will not block. When you get a select hit, that does not guarantee that a future operation will not block.
strlen(buff)+10
What's the reasoning behind the +10?