I am stuck with my UDP talker app.
The goal for the moment is to initialize the server, register a client and then proceed to send something to that client.
I've worked my way through Beej's network guide and coded the following library implementation:
This inizializes the server
int init_udp_server(const char *port_string){
/** Check the input data **/
if(port_string == NULL)
port_string = DEFAULT_PORT;
/** Get the information for the server **/
memset(&addrinfo_hints, 0, sizeof addrinfo_hints);
/* Use either protocol (v4, v6) */
addrinfo_hints.ai_family = AF_UNSPEC;
/* Use UDP socket type */
addrinfo_hints.ai_socktype = SOCK_DGRAM;
/* Use system IP */
addrinfo_hints.ai_flags = AI_PASSIVE;
if( (ret = getaddrinfo(NULL, port_string, &addrinfo_hints, &addrinfo_server))
!= 0 ){
printf("Server:getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
/** Loop through the list returned by getaddrinfo and get socket **/
for( addrinfo_queue = addrinfo_server; addrinfo_queue != NULL;
addrinfo_queue = addrinfo_queue->ai_next){
if((sockfd = socket(addrinfo_queue->ai_family,
addrinfo_queue->ai_socktype, addrinfo_queue->ai_protocol)) == -1){
error("Server: get socket failed");
continue;
}
if(bind(sockfd, addrinfo_queue->ai_addr, addrinfo_queue->ai_addrlen)
== -1){
close(sockfd);
error("Server: Bind to socket error");
continue;
}
break;
}
/* If we got to addrinfo_queue == NULL, we did not get a valid socket */
if(addrinfo_queue == NULL){
error("Server: Could not bind a socket");
return -1;
}
/* We do not need the addrinfo_server anymore */
freeaddrinfo(addrinfo_server);
return 0;
}
This registers the client
int udp_server_setup_client(const char *client_addr, const char *port_string, int client_nr){
/** Check the input data **/
if(port_string == NULL)
port_string = DEFAULT_PORT;
if(client_addr == NULL){
error("No valid client list");
return -1;
}
if(client_nr < 0 || client_nr > 7){
error("No valid client Nr.");
return -1;
}
memset(&addrinfo_hints, 0, sizeof addrinfo_hints);
/* Use either protocol (v4, v6) */
addrinfo_hints.ai_family = AF_UNSPEC;
/* Use UDP socket type */
addrinfo_hints.ai_socktype = SOCK_DGRAM;
/* Get the information for the client */
if( (ret = getaddrinfo( client_addr, port_string, &addrinfo_hints,
¤t)) != 0 ){
printf("Client:getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
else{
/* We read out the IP, kind of a nice check to see wheter all went fine */
char ip4[INET_ADDRSTRLEN];
struct sockaddr_in *sa = (struct sockaddr_in*) current->ai_addr;
inet_ntop(AF_INET, &(sa->sin_addr),ip4, INET_ADDRSTRLEN);
printf("Clients address: %s\n",ip4);
addrinfo_clients[client_nr] = current;
}
return 0;
}
And finally this is for writing
int udp_server_write(const char *buffer, int buffer_size, int client_nr){
/* Sanity check of the input */
if(client_nr > (MAX_NR_CLIENTS - 1) || client_nr < 0){
error("Not a valid client");
return -1;
}
if(buffer == NULL){
error("Not a valid buffer address");
return -1;
}
/* Just so we type less */
current = addrinfo_clients[client_nr];
socklen = sizeof current->ai_addr;
if((ret = sendto(sockfd, (void*)buffer, buffer_size, 0,
(sockaddr*)current->ai_addr, socklen)) == -1){
printf("Failed to send message to client %i\n", client_nr);
printf("Error Code: %s\n",gai_strerror(ret));
return -1;
}
else if(ret < buffer_size){
printf("Wrote only %i of %i bytes\n", ret, buffer_size);
return -1;
}
return ret;
}
I call the functions like this
init_udp_server("3334");
udp_server_setup_client("192.168.1.5", "3334", 0);
udp_server_write(send_buf, 256, 0);
As soon as sendto() is called I get an error:
Failed to send message to client 0
Error Code: Bad value for ai_flags
I checked it with gdb and found that the addrinfo struct is filled correctly, and the address of the client is valid.
Any one an idea where to look? I am running out of ideas...
thanks, wenzlern
When calling sendto(), the last parameter is being set to sizeof current->ai_addr, which is wrong. current->ai_addr is defined as a sockaddr* pointer, so sizeof current->ai_addr will always return 4 on a 32-bit system and 8 on a 64-bit system. It just happens that IPv4 addresses are 4 bytes in size, so sizeof current->ai_addr will only work for IPv4 addresses on 32-bit systems, but will always fail for IPv6 addresses on 32-bit systems and all addresses on 64-bit systems. You need to use current->ai_addrlen instead of sizeof.
Also, passing -1 to gai_strerror() is not valid. It expects you to pass in a real error code, such as the return value of getaddrinfo() and getnameinfo(). sendto() does not return an actual error code. When it fails, you have to use WSAGetLastError() on Windows or errno on other systems to get the actual error code.
Try this:
if ((ret = sendto(sockfd, (char*)buffer, buffer_size, 0, (sockaddr*)current->ai_addr, current->ai_addrlen)) == -1)
{
#ifdef _WIN32
ret = WSAGetLastError();
#else
ret = errno;
#endif
printf("Failed to send message to client %i\n", client_nr);
printf("Error Code: (%d) %s\n", ret, gai_strerror(ret));
return -1;
}
Related
I have a UDP Server which sends data continuously. I want to receive all the packets sent by the server.
On server side I have two threads. One thread continuously reads data from the file and puts into deque. Another thread reads data from the deque and sends to the UDP client continuously. The client code continuously receives data from the server.
I have variables to keep the count of the number of bytes sent in server code and the number of bytes received in client code.
There is huge difference between the two. The server sends about 93 MB but the client receives only 3 - 5 MB.
How can I receive all the data sent by the Server?
Please find the server and client code below.
Server Code:
#define MAX_BUFFER_SIZE 1400
typedef struct
{
T_UCHAR buffer[MAX_BUFFER_SIZE];
DWORD buf_size;
}RAWDATA_LOG;
deque<RAWDATA_LOG> m_RawdataLog;
void TransmitContinuous()
{
if (m_sock_type_tcp == SOCK_UDP)
{
fileReadComplete=false;
//start data transmission thread
pWin_thread=AfxBeginThread(StartDataTransmitThread, (LPVOID) this);
ReadFromFile();
}
}
void ReadFromFile()
{
int bytesRead=0;
m_no_of_bytes = MAX_BUFFER_SIZE;
BYTE input_buf[MAX_BUFFER_SIZE]={'\0'};
GetDlgItemText(IDEBC_FILENAME,m_fileInput);
m_InputFile=NULL;
/*opening the file to read*/
m_InputFile = _tfopen(m_fileInput,L"rb");
if(m_InputFile == NULL)
{
AfxMessageBox(L"Unable to open the Input file");
}
else
{
while(!feof(m_InputFile))
{
bytesRead=fread(input_buf,1,m_no_of_bytes,m_InputFile);
writeRawdataToDeque(input_buf,m_no_of_bytes);
noofBytesReadfromFile+=bytesRead;
}
fileReadComplete=true;
}
}
void writeRawdataToDeque(T_UCHAR *buffer,T_S32 size)
{
T_S32 temp_size = size;
T_S32 size_counter = 0;
RAWDATA_LOG temp_rawDataStruct;
while(temp_size>0)
{
if(temp_size <= MAX_BUFFER_SIZE)
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],temp_size);
temp_rawDataStruct.buf_size = temp_size;
noofBytesWrittentoDeque+=temp_size;
}
else
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],sizeof(temp_rawDataStruct.buffer));
temp_rawDataStruct.buf_size = MAX_BUFFER_SIZE;
noofBytesWrittentoDeque+=MAX_BUFFER_SIZE;
}
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
m_RawdataLog.push_back(temp_rawDataStruct);
datalock.Unlock();
memset(&temp_rawDataStruct,0,sizeof(temp_rawDataStruct));
size_counter += MAX_BUFFER_SIZE;
temp_size = temp_size - MAX_BUFFER_SIZE;
}
}
unsigned int StartDataTransmitThread (LPVOID param)
{
RAWDATA_LOG temp_rawDataBuf;
int byesWritten=0;
CString tmpStr;
while(1)
{
if(!m_RawdataLog.empty())
{
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
temp_rawDataBuf = m_RawdataLog.front();
m_RawdataLog.pop_front();
datalock.Unlock();
//transmit the data through socket
byesWritten=WritetoClient(clientIp,clientPort,(const LPBYTE)&temp_rawDataBuf, MAX_BUFFER_SIZE);
noofBytesTransmitted+=byesWritten;
}
else
{
if(fileReadComplete == true)
{
break;
}
}
}
return true;
}
bool CreateServer(char ipaddr[],int port)
{
sockaddr_in ServerSockAddr;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
ServerSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
ServerSockAddr.sin_family = AF_INET;
ServerSockAddr.sin_port = htons(2011);
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
MessageBox(L"WSAStartup failed with error:" + m_wsaErr);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (INVALID_SOCKET != sock)
{
if ( SOCKET_ERROR == bind(sock,(struct sockaddr *) & ServerSockAddr, sizeof(ServerSockAddr)))
{
int b= GetLastError();
closesocket( sock );
return false;
}
}
else
{
closesocket( sock );
return false;
}
m_hComm = (HANDLE) sock;
}
int WritetoClient(char ipaddr[],int port,BYTE buf[],int len)
{
sockaddr_in clientSockAddr;
int res=0;
SOCKET s = (SOCKET) m_hComm;
clientSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
clientSockAddr.sin_family = AF_INET;
clientSockAddr.sin_port = htons(port);
res = sendto( s, (const char *)buf, len, 0, (SOCKADDR *) &clientSockAddr, sizeof(clientSockAddr));
return res;
}
Client Code:
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32")
#define BUFSIZE 1000000
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET sockfd;
int portno, n;
int serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
char *hostname;
char buf[BUFSIZE];
int BytesReceived=0;
int buff_size=1000000;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error:");
return 1;
}
/* socket: create the socket */
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sockfd < 0)
{
printf("ERROR opening socket");
}
else
{
/* build the server's Internet address */
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(2010);
serveraddr.sin_addr.s_addr=inet_addr("192.168.11.80");
/* send the message to the server */
serverlen = sizeof(serveraddr);
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char *)(&buff_size), sizeof(buff_size));
if ( SOCKET_ERROR == bind(sockfd,(struct sockaddr *) & serveraddr, sizeof(serveraddr)))
{
printf("Bind Error");
int a = GetLastError();
printf("Error ID:%d",a);
}
else
{
printf("Reading From Server:\n");
while(1)
{
n = recvfrom(sockfd, buf, sizeof(buf), 0,(struct sockaddr *) &serveraddr, &serverlen);
if (n < 0)
{
printf("ERROR in recvfrom\n");
int b = GetLastError();
printf("Error ID:%d\n",b);
}
else
{
BytesReceived+=n;
TRACE("\nTotal Bytes Received:%d\n",BytesReceived);
}
}
}
}
getchar();
return 0;
}
I see a couple of issues with your code.
On the server side, you are binding the server's socket to 192.168.11.80 AND you are sending packets to 192.168.11.80 as well, instead of sending them to whichever IP address is specified in the ipaddr parameter of the WritetoClient() function.
On the client side, you are bind()'ing the client's socket to the server's IP address.
This setup will only work if the client and server are running on the same machine. It will not work between multiple machines connected through a network.
You need to bind the client to an IP address that is local to the client's own machine, not to the server's IP address. And your server needs to send packets to the IP address that the client is actually bound to.
If you want to ensure that your client receives data only from the server's IP address, and not from other machines that may happen to be sending data over the same network, you can optionally connect() the client's socket to the server's IP address (yes, you can use connect() with UDP).
bind() is for establishing a socket's local IP address. connect() is for establishing a socket's remote/peer IP address.
Since you are (potentially) not binding the client's socket correctly, and/or (potentially) not sending to the correct IP, you are likely receiving data that you are not expecting from somewhere else. That could explain the large discrepancy you are seeing. I would suggest having your client output the data it actually receives, so you can make sure it is receiving what you are expecting, eg:
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR)
{
int b = WSAGetLastError();
printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
BytesReceived += n;
TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}
I have written a code to create and set the properties of VLAN interface. I am able to set the IP address, however the I am facing problem in setting the gateway address and reading the device flags. Please have a look at code and suggest what could be wrong.
I am getting error in the function generic_ioctrlcall.
/**
* Create socket function
*/
int create_socket()
{
int sockfd = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd == -1){
fprintf(stderr, "Could not get socket.\n");
return -1;
}
return sockfd;
}
/**
* Generic ioctrlcall to reduce code size
*/
int generic_ioctrlcall(int sockfd, u_long *flags, struct ifreq *ifr) {
if (ioctl(sockfd, (long unsigned int)flags, &ifr) < 0) {
fprintf(stderr, "ioctl: %s\n", (char *)flags);
return -1;
}
return 1;
}
/**
* Set route with metric 100
*/
int set_route(int sockfd, char *gateway_addr, struct sockaddr_in *addr) {
struct rtentry route;
int err = 0;
memset(&route, 0, sizeof(route));
addr = (struct sockaddr_in*) &route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(gateway_addr);
addr = (struct sockaddr_in*) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr("0.0.0.0");
addr = (struct sockaddr_in*) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr("0.0.0.0");
route.rt_flags = RTF_UP | RTF_GATEWAY;
route.rt_metric = 100;
if ((err = ioctl(sockfd, SIOCADDRT, &route)) < 0) {
fprintf(stderr, "ioctl: %s\n", (char *)flags);
return -1;
}
return 1;
}
/**
* Set ip function
*/
int set_ip(char *iface_name, char *ip_addr, char *gateway_addr)
{
if(!iface_name)
return -1;
struct ifreq ifr;
struct sockaddr_in sin;
int sockfd = create_socket();
sin.sin_family = AF_INET;
// Convert IP from numbers and dots to binary notation
inet_aton(ip_addr,&sin.sin_addr.s_addr);
/* get interface name */
strncpy(ifr.ifr_name, iface_name, IFNAMSIZ);
/* Read interface flags */
generic_ioctrlcall(sockfd, (u_long *)"SIOCGIFFLAGS", &ifr);
/*
* Expected in <net/if.h> according to
* "UNIX Network Programming".
*/
#ifdef ifr_flags
# define IRFFLAGS ifr_flags
#else /* Present on kFreeBSD */
# define IRFFLAGS ifr_flagshigh
#endif
// If interface is down, bring it up
if (ifr.IRFFLAGS | ~(IFF_UP)) {
ifr.IRFFLAGS |= IFF_UP;
generic_ioctrlcall(sockfd, (u_long *)"SIOCSIFFLAGS", &ifr);
}
// Set route
set_route(sockfd, gateway_addr, &sin);
memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
// Set interface address
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
fprintf(stderr, "Cannot set IP address. ");
perror(ifr.ifr_name);
return -1;
}
#undef IRFFLAGS
return 0;
}
Many problems here. The proximate cause of your difficulty is that the second argument to ioctl is a long integer, not a pointer to a character string.
generic_ioctrlcall(sockfd, (u_long *)"SIOCGIFFLAGS", &ifr);
does not create a pointer to the integer value of SIOCGIFFLAGS which is presumably what you intended. Other issues:
(1) Since ioctl takes a long integer as the second argument, why did you want to pass a pointer to an integer? Just pass the integer as argument.
(2) If you do wish to pass a pointer to an integer, you would need to do something like this:
u_long ioctl_arg = SIOCGIFFLAGS;
generic_ioctrlcall(sockfd, &ioctl_arg, &ifr);
(3) You cannot convert a pointed-to integer to an integer simply by casting it. You need to dereference the pointer. That is:
Change:
if (ioctl(sockfd, (long unsigned int)flags, &ifr) < 0) {
to:
if (ioctl(sockfd, *flags, &ifr) < 0) {
(4) on an ioctl failure, you should be printing out errno (or, better yet, its text translation) after the failure in order to figure out what went wrong:
if (ioctl(sockfd, *flags, &ifr) < 0) {
fprintf(stderr, "ioctl: flags %ld errno %d/%s\n", *flags, errno, strerror(errno));
And by the way, it seems unlikely that the errno from any of your generic_ioctl calls would be ENODEV (No such device) -- as your title implies. It seems much more likely that the errno would be EINVAL since the chances of your pointer-to-character-string forming a valid ioctl integer argument are very slim.
I'm a new to socket programming. I tried to connect a server to multiple clients and i have two problems in it. 1)I can't send a message unless i get a reply i.e if a client connects and sends a message,client can't send a message again until it gets reply from server. If client types some message it stores the messages and it sends the message after it gets a reply.
2)I want to restrict the number of connections to 1 and if some one connects no one else should connect until the client the client quits. If the client quits the one who is first in waiting should be connected.
server
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define MYPORT 3490 /* the port users connect to */
#define BACKLOG 0 /* max no. of pending connections in server queue */
#define MAXDATASIZE 200
void sigchld_handler(int s)
{
while( wait( NULL) > 0); /* wait for any child to finish */
}
int main( void)
{
int listenfd;
/* listening socket */
int connfd;
/* connection socket */
struct sockaddr_in server_addr; /* info for my addr i.e. server */
struct sockaddr_in client_addr; /* client's address info */
int sin_size;
/* size of address structure */
struct sigaction sa; /* deal with signals from dying children! */
int yes = 1;
char clientAddr[ 20]; /* holds ascii dotted quad address */
if ((listenfd = socket( AF_INET, SOCK_STREAM, 0)) == -1)
{
perror( "Server socket");
exit( 1);
}
/* Set Unix socket level to allow address reuse */
if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,&yes, sizeof( int)) == -1)
{
perror( "Server setsockopt");
exit( 1);
}
sin_size = sizeof( server_addr);
memset( &server_addr, 0, sin_size);
/* zero struct */
server_addr.sin_family = AF_INET;
/* host byte order ... */
server_addr.sin_port = htons( MYPORT); /* . short, network byte order */
server_addr.sin_addr.s_addr = INADDR_ANY; /* any server IP addr */
if( bind( listenfd, (struct sockaddr *)&server_addr,sizeof( struct sockaddr)) == -1)
{
perror( "Server bind");
exit( 1);
}
if( listen( listenfd, BACKLOG) == -1)
{
perror( "Server listen");
exit( 1);
}
/* Signal handler stuff */
sa.sa_handler = sigchld_handler; /* reap all dead processes */
sigemptyset( &sa.sa_mask);
sa.sa_flags = SA_RESTART;
if( sigaction( SIGCHLD, &sa, NULL) == -1)
{
perror( "Server sigaction");
exit( 1);
}
while( 1)
{
/* main accept() loop */
sin_size = sizeof( struct sockaddr_in);
if( (connfd = accept( listenfd,(struct sockaddr *)&client_addr, &sin_size)) == -1)
{
perror( "Server accept");
continue;
}
strcpy( clientAddr, inet_ntoa( client_addr.sin_addr));
printf( "Server: got connection from %s\n", clientAddr);
if( !fork())
{
/* the child process dealing with a client */
char msg[ MAXDATASIZE];
int numbytes;
close( listenfd); /* child does not need the listener */
msg[ 0] = '\0';
/* no message yet! */
do
{
if( (numbytes =recv( connfd, msg, MAXDATASIZE -1, 0)) == -1)
{
perror( "Server recv");
exit( 1);
/* error end of child */
}
msg[ numbytes] = '\0';
/* end of string */
fprintf( stderr, "Message received: %s\n", msg);
do
{
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
printf( "Message to send: ");
scanf( "%s", msg);
if( send( connfd, msg, strlen( msg), 0) == -1)
{
perror( "server send");
//exit(1);
}
/* error end of child */
}
while( strcmp( msg, "quit") != 0);
if( strcmp( msg, "quit") == 0)
{
close( connfd);
exit(0);
}
//close( connfd);
//exit(0);
/* end of child! */
}
while(1);
//fork();
//close(connfd); /* parent does not need the connection socket */
return 0;
}
}
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/* for gethostbyname() */
#define PORT 3490
/* server port the client connects to */
#define MAXDATASIZE 100 /* max bytes to be received at once */</i>
int main( int argc, char * argv[])
{
int sockfd, numbytes;
char buf[ MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* server address info */
char msg[ MAXDATASIZE];
if( argc != 2) {
fprintf( stderr, "usage: client hostname\n");
exit( 1);
}
/* resolve server host name or IP address */
if( (he = gethostbyname( argv[ 1])) == NULL) { /* host server info */
perror( "Client gethostbyname");
exit( 1);
}
if( (sockfd = socket( AF_INET, SOCK_STREAM, 0)) == -1) {
perror( "Client socket");
exit( 1);
}
memset( &their_addr, 0, sizeof( their_addr));
/* zero all */
their_addr.sin_family = AF_INET;
/* host byte order .. */
their_addr.sin_port = htons( PORT);
/* .. short, network byte order */
their_addr.sin_addr = *((struct in_addr *)he -> h_addr);
if( connect( sockfd, (struct sockaddr *)&their_addr,
sizeof( struct sockaddr)) == -1) {
perror( "Client connect");
exit( 1);
}
do {
printf( "Message to send: ");
scanf( "%s", msg);
if( (numbytes = send( sockfd, msg, strlen( msg), 0)) == -1) {
perror( "Client send");
continue;
}
if( (numbytes = recv( sockfd, buf, MAXDATASIZE - 1, 0)) == -1) {
perror( "Client recv");
continue;
}
buf[ numbytes] = '\0';
/* end of string char */
printf( "Received: %s\n", buf);
} while( strcmp( msg, "quit") != 0);
close( sockfd);
return 0;
}
dear you have to use multithreading for this start a new thread to handle new connection
in that thread also use separate threads for receiving data and sending data ...
1)I can't send a message unless i get a reply i.e if a client connects
and sends a message,client can't send a message again until it gets
reply from server.
That's no wonder, since you have programmed this sequential arrangement of scanf and recv in your client's do loop. To handle message input and socket receipt in order of appearance, we can use select; your do loop could then look like:
do
{ fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(sockfd, &fds); // set of descriptors holds stdin and socket
printf("Message to send: "), fflush(stdout);
if (select(sockfd+1, &fds, NULL, NULL, NULL) < 0) break; // error?
// see which descriptors of set are ready
if (FD_ISSET(STDIN_FILENO, &fds))
{ // it is the standard input
scanf("%s", msg);
numbytes = send(sockfd, msg, strlen(msg), 0);
if (numbytes == -1) perror("Client send");
}
if (FD_ISSET(sockfd, &fds))
{ // this is the peer's message or termination
numbytes = recv(sockfd, buf, MAXDATASIZE - 1, 0);
if (numbytes <= 0)
{
perror("Client recv");
break; // no more data from peer, so close the connection
}
buf[numbytes] = '\0'; /* end of string char */
printf("Received: %s\n", buf);
}
} while (strcmp(msg, "quit") != 0);
2)I want to restrict the number of connections to 1 and if some one
connects no one else should connect until the client the client quits.
We can achieve this simply by not forking a server process after we accept a client connection request, but rather handling the message transfer in the one and only server task itself (quite similar as shown above for the client); just omit the lines if( !fork()) as well as return 0; instead uncomment the close(connfd); and don't forget to break out of the do loop when recv returns a nonpositive value.
I'm trying to establish UDP communication between a MAC OS and an iPod through Wi-Fi, at this point I'm able to send packets from the iPod and I can see those packets have the right MAC and ip addresses (I'm using wireshark to monitor the network) but the MAC receives the packets only when the wireshark is on, otherwise recvfrom() returns -1.
When I try to transmit from MAC to iPhone I have the same result, I can see the packets are sent but the iPhone doesn't seem to get them.
I'm using the next code to send:
struct addrinfo hints;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(IP, SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
while (cond)
sntBytes += sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen);
return 0;
and this code to receive:
struct addrinfo hints, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use to AF_INET to force IPv4 my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
addr_len = sizeof their_addr;
fcntl(sockfd, F_SETFL,O_NONBLOCK);
int rcvbuf_size = 128 * 1024; // That's 128Kb of buffer space.
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf_size, sizeof(rcvbuf_size));
printf("listener: waiting to recvfrom...\n");
while (cond)
rcvBytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len);
return 0;
What am I missing?
It would be good to get some more information about the length of data you are sending.
I will assume you are trying to send an ASCII string.
Also, this appears to be either never called or an infinite send loop:
while (cond)
sntBytes += sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen);
You might want to use code that actually includes some error checking:
Send String
int sendResult = send( connectedSocket, stringBuffer, stringLength, 0 );
if (sendResult == -1) {
perror("Error while trying to send string!");
}
else {
NSLog(#"String '%s' sent successfully", stringBuffer );
}
Receive String
memset( ReceiveBuffer, '\0', sizeof(ReceiveBuffer) );
int receiveResult = recv( connectedSocket, ReceiveBuffer, sizeof(ReceiveBuffer), 0);
if ( receiveResult == -1 ) {
perror("recv");
}
else {
NSLog(#"String received successfully: '%s'", ReceiveBuffer );
}
It seems my questions are strange and i'm not getting enough help but I'm back.
I've another strange question which needs to be solved in emergency.
I'm developing an iPhone app. which uses libssh 2 for commands execution through iPhone over remote host. It's okay and working all methods and commands if i execute them in single.
My problem is,
consider a sequence of commands,
pwd
=> o/p will be /Users/mac01
cd xyz
=> nothing as o/p
pwd
=> o/p will be /Users/mac01/xyz
So, my question is to save the last state of the command which has been executed... but what I'm getting as o/p is
/Users/mac01
after second pwd command execution, which is wrong.
So, could anyone help me out with such type of problems..? Thanks in advance.
I'm using libssh 2.0 library.
The method executing command:
char* cmd_exec(const char *commandline, const char *host, const char *username, const char *password, int port){
int sock, rc, bytecount = 0;
char *cmd_contents;
if(!he)
{
struct sockaddr_in sin;
ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
endif
/* Init and Make Socket Connection */
/* Start Socket Connection */
sock = socket(AF_INET, SOCK_STREAM, 0);
ifndef WIN32
fcntl(sock, F_SETFL, 0);
endif
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
/*sin.sin_addr.s_addr = inet_addr(host);
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}*/
//const char *c = getIPFromHost("pepsi");
//sin.sin_addr.s_addr = inet_addr(c);
/* IP Address Calculation */
he = gethostbyname(host);
if(!he)
return "Invalid hostname";
struct in_addr **addr_list;
addr_list = (struct in_addr **)he->h_addr_list;
//for(int i = 0; addr_list[i] != NULL; i++) {
if(addr_list != NULL){
sin.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
//printf("%s", inet_ntoa(*addr_list[0]));
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}
}
}
/* End Socket Connection */
// Initialize and create Session Instance
if(!session)
{
session = libssh2_session_init();
if ( !session )
{
fprintf( stderr, "Error initializing SSH session\n" );
return "SESSIONFAILURE";
}
/* Since we have set non-blocking, tell libssh2 we are non-blocking */
//libssh2_session_set_blocking(session, 0);
// Session starting
if (libssh2_session_startup(session, sock)) {
fprintf(stderr, "Failure establishing SSH session\n");
return "SESSIONFAILURE";
}
/* Authenticate via password */
if(strlen(password) != 0){
if ( libssh2_userauth_password( session, username, password ) )
{
fprintf( stderr, "Unable to authenticate user [%s]"
"(wrong password specified?)\n", username );
return "AUTHENTICATIONFAILURE";
}
}else{
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
return "AUTHENTICATIONFAILURE";
}
}
//libssh2_session_set_blocking(session, 1);
}
// Open a session channel for command execution
if(!channel)
{
channel = libssh2_channel_open_session(session);
if (!channel) {
fprintf(stderr, "Unable to open a session\n");
return "SESSIONFAILURE";
}
// Execute a command through channel
while( (rc = libssh2_channel_shell(channel)) ==
//while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 ) // if command execution failed
{
fprintf(stderr,"Error\n");
return "CMDFAILURE";
}
}
//libssh2_channel_write(channel,commandline,strlen(commandline));
do {
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, commandline, sizeof(commandline));
if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
}
} while (rc == 0);
while (libssh2_channel_send_eof(channel) == LIBSSH2_ERROR_EAGAIN);
/* read channel output */
/* Start channel read */
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
// char *tcontents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
bytecount += rc;
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
fprintf(stderr, "\n");
}
else {
//fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
/* End channel read */
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
/* closing channel */
int exitcode = 127;
// while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
}
//
libssh2_channel_free(channel); // freeup memory
channel = NULL;
/*
libssh2_session_disconnect( session, "" ); // closing session
libssh2_session_free( session ); // free up memory
close( sock ); // closing socket
*/
return cmd_contents;
}
Try this maybe it works... i havent tried it but you can get enough idea and may be the proper solution
libssh2_session_set_blocking(session, 0);
char buffer[0x4000]; rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents)
{
free(cmd_contents);
}
buffer[i] = '\0';
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
hAPPY cODING...
libssh2_session_set_blocking(session, 0);
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
buffer[i] = '\0';
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}