C Multithreading for Windows while connection between TCPIP - c

I hope I can explain. I am new in c programming and trying to send and receive binary file using TCPIP. Server should receive multiple files at a time when client send it. I creaded a bat file for send to server. There is no problem if file is 2 or 3 but while trying to send about 5 file sometimes show error. Actually file is not receiving properly. I used
multithreading Synchronization of Semaphore method
The result of receiving side(server) is as follows while printing:
file name (5000.dat)
Invalid argumen(5000.dat)
completetfile name (5120.dat)
(5120.dat) complete
file name (8192.dat)
(8192.dat) complete
file name (10240.dat)
(10240.dat) complete
Some text is misplassed above and each time shows different result. Sometimes reveive and write file properly and sometimes some files can't read.
My code of receving side is as follows:
#include <stdio.h>
#include <winsock2.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <process.h>
#include <windows.h>
void fileReceive(void *param);
HANDLE semaphore;
HANDLE threadHandle;
int main(int argc, char *argv[]){
if (argc > 1) {
goto l_param_error;
}
WSADATA wsaData; // Contains information about the Windows Sockets implementation
SOCKET sock0; // creates a socket that is bound to a specific transport service provider.
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
SOCKET sock; // creates a socket that is bound to a specific transport service provider
// Initiates use of the Winsock DLL by a process.
int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (error != 0) {
goto l_WSAIni_error;
}
addr.sin_family = AF_INET;// internetwork: UDP, TCP, etc.
addr.sin_port = htons(8080);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
sock0 = socket(AF_INET, SOCK_STREAM, 0);
if (sock0 == INVALID_SOCKET) {
goto l_socket_error;
}
// associates a local address with a socket
if (bind(sock0, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
goto l_bind_error;
}
while (1) {
// places a socket in a state in which it is listening for an incoming connection
if (listen(sock0, 1) != 0) {
goto l_socket_conn_setup_error;
}
len = sizeof(client);
// The accept function permits an incoming connection attempt on a socket.
sock = accept(sock0, (struct sockaddr *)&client, &len);
if (sock == INVALID_SOCKET) {
goto l_error_accpet;
}
semaphore = CreateSemaphore(0, 1, 1, 0);
threadHandle = (HANDLE)_beginthread(&fileReceive, 0, &sock);
if (threadHandle == 0) {
printf("Thread handle error");
return 1;
}
CloseHandle(semaphore);
}
WSACleanup();
return 0;
}
void fileReceive(void *param) {
int n = 0;
int sock = *((int *)param);
unsigned char buf[1];
unsigned char buff[256] = { 0 };
FILE *fp = NULL;
memset(buff, 0, sizeof(buff));
WaitForSingleObject(semaphore, INFINITE);
// Receive file name
int recvFile = recv(sock, buff, 255, 0);
ReleaseSemaphore(semaphore, 1, 0);
if ((recvFile == 0) || (recvFile == -1)) {
goto l_recv_error;
}
fp = fopen(buff, "wb+");
if (fp != NULL) {
printf("file name (%s)\n", buff);
while (n = recv(sock, &buf[0], 1, 0) > 0) {
size_t written = fwrite(&buf, sizeof(buf), 1, fp);
if (written != 1) {
goto l_write_error;
}
}
printf("(%s) complete\n", buff);
}
else {
goto l_fp_error;
}
fclose(fp);
closesocket(sock);
_endthread();
CloseHandle(threadHandle);
}

Unfortunately, you have a long list of problems. Bluntly, it seems that you don't understand TCP (it's a byte stream protocol) and it seems that you don't understand what problems thread synchronization solves and how to use it. Given this, you are attempting a task that's way beyond your capabilities and should attempt much simpler tasks first. Start with TCP code that doesn't use threads or threading code that doesn't use TCP so you don't have to get everything right at once.
Here are some of the problems:
You pass &sock to the thread. But then change the value of sock, possibly before the thread can read it.
You call recv on the TCP connection to get the filename and just assume you'll read all, and only, the filename. TCP has no way to "glue" bytes together into a message. If you want to send and receive messages, you must define a message protocol and implement it on top of TCP.
Your semaphore doesn't actually do anything. You don't use it to communicate or synchronize anything.
You write 256 bytes every time you read 1.

Related

How to program non-blocking socket on connect and select? [duplicate]

This question already has an answer here:
Basic non blocking tcp connect example for C [closed]
(1 answer)
Closed 12 months ago.
I am trying to write a C code that connects using non-blocking TCP socket along with select(). When I read the man page about EINPROGRESS, I feel a little bit confused.
EINPROGRESS
The socket is nonblocking and the connection cannot be completed immediately. It is possible to
select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates
writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine
whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one
of the usual error codes listed here, explaining the reason for the failure).
Is there any sample code I can refer to? Although it is a pretty old question, I don't see anyone post a complete working code. Some suggest to use connect twice but I don't know exactly how.
Sure, below is a little C program that uses a non-blocking TCP connect to connect to www.google.com's port 80, send it a nonsense string, and print out the response it gets back:
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
static void SendNonsenseCommand(int sock)
{
const char sendString[] = "Hello Google! How are you!\r\n\r\n";
if (send(sock, sendString, sizeof(sendString), 0) != sizeof(sendString)) perror("send()");
}
int main(int argc, char ** argv)
{
// Create a TCP socket
const int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {perror("socket"); return 10;}
// Set the TCP socket to non-blocking mode
const int flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {perror("fcntl(F_GETFL)"); return 10;}
if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0) {perror("fcntl(F_SETFL)"); return 10;}
// Get the IP address of www.google.com
struct hostent * he = gethostbyname("www.google.com");
if (he == NULL) {printf("Couldn't get a hostent for www.google.com\n"); return 10;}
// Start a non-blocking/asynchronous TCP connetion to port 80
struct sockaddr_in saAddr;
memset(&saAddr, 0, sizeof(saAddr));
saAddr.sin_family = AF_INET;
saAddr.sin_addr = *(struct in_addr*)he->h_addr;
saAddr.sin_port = htons(80);
const int connectResult = connect(sock, (const struct sockaddr *) &saAddr, sizeof(saAddr));
int isTCPConnectInProgress = ((connectResult == -1)&&(errno == EINPROGRESS));
if ((connectResult == 0)||(isTCPConnectInProgress))
{
if (isTCPConnectInProgress == 0) SendNonsenseCommand(sock);
// TCP connection is happening in the background; our event-loop calls select() to block until it is ready
while(1)
{
fd_set socketsToWatchForReadReady, socketsToWatchForWriteReady;
FD_ZERO(&socketsToWatchForReadReady);
FD_ZERO(&socketsToWatchForWriteReady);
// While connecting, we'll watch the socket for ready-for-write as that will tell us when the
// TCP connection process has completed. After it's connected, we'll watch it for ready-for-read
// to see what Google's web server has to say to us.
if (isTCPConnectInProgress) FD_SET(sock, &socketsToWatchForWriteReady);
else FD_SET(sock, &socketsToWatchForReadReady);
int maxFD = sock; // if we were watching multiple sockets, we'd compute this to be the max value of all of them
const int selectResult = select(maxFD+1, &socketsToWatchForReadReady, &socketsToWatchForWriteReady, NULL, NULL);
if (selectResult >= 0)
{
if ((FD_ISSET(sock, &socketsToWatchForWriteReady))&&(isTCPConnectInProgress))
{
printf("Socket is ready for write! Let's find out if the connection succeeded or not...\n");
struct sockaddr_in junk;
socklen_t length = sizeof(junk);
memset(&junk, 0, sizeof(junk));
if (getpeername(sock, (struct sockaddr *)&junk, &length) == 0)
{
printf("TCP Connection succeeded, socket is ready for use!\n");
isTCPConnectInProgress = 0;
SendNonsenseCommand(sock);
}
else
{
printf("TCP Connection failed!\n");
break;
}
}
if (FD_ISSET(sock, &socketsToWatchForReadReady))
{
char buf[512];
const int numBytesReceived = recv(sock, buf, sizeof(buf)-1, 0);
if (numBytesReceived > 0)
{
buf[numBytesReceived] = '\0'; // ensure NUL-termination before we call printf()
printf("recv() returned %i: [%s]\n", numBytesReceived, buf);
}
else if (numBytesReceived == 0)
{
printf("TCP Connection severed!\n");
break;
}
else perror("recv()");
}
}
else {perror("select()"); return 10;}
}
}
else perror("connect()");
close(sock); // just to be tidy
return 0;
}

How make UDP socket receive packets from multiple senders and run the commands in each packet and print stdout/stderr back to the original sender?

I run the following C program with the following command in one terminal.
./main 1337
Then I run the following command in another terminal.
nc -u localhost 1337 <<< 'ls -l --color=always'
But it does not allow UDP from multiple senders.
Could anybody show me how to make the server to handle UDP packets from multiple senders simultaneously and send the stdout/stderr back to the respective sender?
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
void perrdie(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd;
if((sockfd=socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perrdie("socket");
}
struct sockaddr_in bind_addr;
bind_addr.sin_family=AF_INET;
bind_addr.sin_port=htons(atoi(argv[1]));
bind_addr.sin_addr.s_addr=INADDR_ANY;
if(bind(sockfd, (struct sockaddr*)(&bind_addr),sizeof(bind_addr))<0) {
perrdie("bind");
}
struct sockaddr src_addr;
socklen_t src_addr_len=sizeof(src_addr);
char buf[1024];
int dgram_len;
if((dgram_len = recvfrom(sockfd, &buf, sizeof(buf), 0, &src_addr, &src_addr_len)) == -1) {
perrdie("recvfrom");
}
if(connect(sockfd, &src_addr, sizeof(src_addr)) == -1) {
perrdie("connect");
}
while(1) {
fputc('^', stdout);
fwrite(buf, sizeof(char), dgram_len, stdout);
fputc('$', stdout);
fflush(stdout);
for(int i=0;i<sizeof(buf) && i<dgram_len;++i) {
if(buf[i]=='\r' || buf[i]=='\n') {
buf[i]=0;
system(buf);
if((dgram_len = recv(sockfd, &buf, sizeof(buf), 0)) == -1) {
perrdie("recv");
}
break;
}
}
}
return 0;
}
EDIT: It seems that it is better to connect system()'s stdout/err to the socket. Remy Lebeau provides a solution without this part. If anybody else knows how to fulfill this part, please add it to the code.
Your server is connect()'ing its UDP socket to the 1st client that sends a command, and then all subsequent sends and reads are only with that specific client.
To allow multiple clients, you need to get rid of connect() altogether, and then call recvfrom() in a loop, using sendto() to send each command's result to the sockaddr that was reported by recvfrom(), eg:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
void perrdie(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perrdie("socket");
}
struct sockaddr_in bind_addr;
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(atoi(argv[1]));
bind_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) < 0) {
perrdie("bind");
}
struct sockaddr_in src_addr;
socklen_t src_addr_len;
char buf[1025], *cmd;
int dgram_len, cmd_len;
while(1) {
src_addr_len = sizeof(src_addr);
if ((dgram_len = recvfrom(sockfd, &buf, sizeof(buf)-1, 0, (struct sockaddr*)&src_addr, &src_addr_len)) < 0) {
perrdie("recvfrom");
}
buf[dgram_len] = '\0';
fputc('^', stdout);
fwrite(buf, sizeof(char), dgram_len, stdout);
fputc('$', stdout);
fflush(stdout);
cmd = strtok(buf, "\n");
while (cmd != NULL) {
cmd_len = strlen(cmd);
if (cmd_len > 0 && cmd[cmd_len-1] == '\r') {
cmd[--cmd_len] = '\0';
}
system(cmd);
// read in and send output back to sender as needed...
sendto(sockfd, YourSystemOutput, YourSystemOutputSize, 0, &src_addr, &src_addr_len);
cmd = strtok(NULL, "\n");
}
}
close(sockfd);
return 0;
}
Datagram (UDP) sockets don't have the concept of a "connection", so it's impossible for any UDP peer to know when its remote peer has disconnected from it. The only information it can get is that it stops receiving packets from its remote peer.
One option is to use timeouts, where it decides it's disconnected if it hasn't received any packets within a certain period of time, but that doesn't work with all higher-level protocols. Another option is to use TCP instead of UDP, which provides transport-level disconnection (via FIN or RST packets).
Note that when you call the connect(2) syscall on a UDP socket, all that's doing is setting a value in memory used for the default destination for any packets sent with send(2). The pair of calls connect(address) and send() on a UDP socket is equivalent to calling sendto(address) on that socket.

Why does a client not close its socket?

I am reading a socket client example from APUE at https://github.com/hayatoito/apue-2e/blob/master/sockets/ruptime.c. I don't find it close or shutdown its socket. Is it true in general that a client doesn't have to close its socket file descriptor? When does a client need to close its socket file descriptor, and when not?
For comparison, its server closes the socket at the end: https://github.com/hayatoito/apue-2e/blob/master/sockets/ruptimed.c
Client:
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>
#define MAXADDRLEN 256
#define BUFLEN 128
extern int connect_retry(int, const struct sockaddr *, socklen_t);
void
print_uptime(int sockfd)
{
int n;
char buf[BUFLEN];
while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0)
write(STDOUT_FILENO, buf, n);
if (n < 0)
err_sys("recv error");
}
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err;
if (argc != 2)
err_quit("usage: ruptime hostname");
hint.ai_flags = 0;
hint.ai_family = 0;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
err_quit("getaddrinfo error: %s", gai_strerror(err));
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if ((sockfd = socket(aip->ai_family, SOCK_STREAM, 0)) < 0)
err = errno;
if (connect_retry(sockfd, aip->ai_addr, aip->ai_addrlen) < 0) {
err = errno;
} else {
print_uptime(sockfd);
exit(0);
}
}
fprintf(stderr, "can't connect to %s: %s\n", argv[1], strerror(err));
exit(1);
}
Server:
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <sys/socket.h>
#define BUFLEN 128
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif
extern int initserver(int, struct sockaddr *, socklen_t, int);
void
serve(int sockfd)
{
int clfd;
FILE *fp;
char buf[BUFLEN];
for (;;) {
clfd = accept(sockfd, NULL, NULL);
if (clfd < 0) {
syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno));
exit(1);
}
if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
sprintf(buf, "error: %s\n", strerror(errno));
send(clfd, buf, strlen(buf), 0);
} else {
while (fgets(buf, BUFLEN, fp) != NULL)
send(clfd, buf, strlen(buf), 0);
pclose(fp);
}
close(clfd);
}
}
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err, n;
char *host;
if (argc != 1)
err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
n = sysconf(_SC_HOST_NAME_MAX);
if (n < 0) /* best guess */
#endif
n = HOST_NAME_MAX;
host = malloc(n);
if (host == NULL)
err_sys("malloc error");
if (gethostname(host, n) < 0)
err_sys("gethostname error");
daemonize("ruptimed");
hint.ai_flags = AI_CANONNAME;
hint.ai_family = 0;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
gai_strerror(err));
exit(1);
}
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr,
aip->ai_addrlen, QLEN)) >= 0) {
serve(sockfd);
exit(0);
}
}
exit(1);
}
Is it true in general that a client doesn't have to close its socket file descriptor?
No, it is not true.
A variant of that belief resulted in a number of keepalive issues in early Microsoft Internet Explorer browsers (versions 1 through 5), that had to be worked around on the server end. (Essentially, the OS did not ensure a proper, full TCP connection termination.)
However, if the process is about to exit, it is not a bug to not close all sockets, because POSIX.1 (the standard that defines this functionality and the C interface used here) says explicitly (in e.g. exit()) that all open streams are closed when the process exits. In theory, it is a similar situation as dynamic memory allocation: it is not necessary for the process to free() all dynamically allocated memory when it exits, because all (non-shared) dynamically allocated memory is automatically freed when the process exits.
In practice, it is much more robust to explicitly close all socket descriptors. This is especially true for TCP connections, because the connection termination involves a FIN and an ACK packet exchange. While one could trust the OS to always get it right, the MSIE example shows reality is much less trustworthy, and being thorough makes for a better user experience.
When does a client need to close its socket file descriptor, and when not?
There are two cases in practice:
When the connection is terminated.
Descriptors are a finite resource, and closing them as soon as they are no longer needed ensures resources are not wasted. There really is no good reason for keeping a socket connection open for any longer than necessary. Certain things, like traversing a filesystem hierarchy using nftw(), are much more efficient when they can use a potentially large number of descriptors, so taking care a process does not run out of them due to programmer laziness is a good idea.
When creating a child process via fork(), that should not have access to that socket connection.
Current Linux, MacOS, FreeBSD, and OpenBSD at least support a close-on-exec flag (often via fcntl(sfd, F_SETFD, FD_CLOEXEC)). In Linux, you can create close-on-exec socket descriptors using socket(domain, type | SOCK_CLOEXEC, protocol) and socket pairs using socketpair(domain, type | SOCK_CLOEXEC, protocol, sfd).
Close-on-exec descriptors are closed when an exec call is successful, replacing that process with whatever else is being executed. Thus, if the fork is followed by an exec or _Exit, and all socket descriptors are close-on-exec, the duplicate sockets are closed "automatically", and you don't need to worry about it.
Note that if your code uses popen(), you better have your socket descriptors close-on-exec, or the command you run may have access to the connections. Pity it is completely nonstandard at this point in time (early 2019).
Do also note that if the child process does not execute another binary, but for example drops privileges (rare for a client), close-on-exec won't do anything. So, closing (in the child process) unneeded duplicates of the socket descriptors, explicitly "by hand", is still important for proper privilege separation. But that is rarely an issue with client applications, more with services and such.
In other words, whenever you wish to terminate the socket connection, or when you have an extraneous duplicate of the socket connection, you close() them.
Allways have to close the socket, anyway it is leaked resource.
There is lot of way to close it, but before the close, be sure the socket data is empty. So you have to call the shutdown, anf after close it.

Server program that listens on two different socket interfaces

Is it possible that a TCP server program can listen on two different socket interface?
Problem Statement:
I've a problem statement where the TCP server will be having two interfaces:
Interface I: For accepting generic data from TCP client (IP address 192.168.5.10:2000)
Interface II: Management Interface for the server (IP address 192.168.5.11:2000)
Interface I: This interface shall receive data from TCP client, processes them & send it back to client.
Interface II: This interface shall receive commands (meant for Servers management purpose). This commands most probably would be sent through telnet.
Current Status:
I already have a thread based TCP server program where I've "Interface I" up & running(I'm able to receive data from multiple clients, process them & send it back)
Can anyone give me some pointers/prototype example on how to add "Interface II" to my TCP server program?
NOTE: TCP server program is written in C programming language for Linux OS
UPDATE
Below is the code fragment I've written so far for listening on one socket. I tried modifying it for listening over two sockets as you've directed but I'm facing trouble while trying to spawn a different thread for the other socket interface. Will it possible for you to modify this to listen on two sockets? It would be really helpful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
void *data_processing_thread(void *arg);
int main(int argc, char **argv)
{
int fdmax, listener, newfd, res;
int optval=1;
socklen_t addrlen;
int server_port = 4000;
/* master, temp file descriptor list */
fd_set *master, *read_fds;
/* client, server address */
struct sockaddr_in server_addr, client_addr;
pthread_t thread;
master = malloc(sizeof(fd_set));
read_fds = malloc(sizeof(fd_set));
FD_ZERO(master);
FD_ZERO(read_fds);
/* create endpoint for communication */
if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("failed to create listener\n");
return -1;
}
/* check if address is already in use? */
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(int)) == -1) {
perror("socket address already in use!\n");
return -1;
}
/* bind */
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(server_port);
memset(&(server_addr.sin_zero), '\0', 8);
if (bind(listener, (struct sockaddr*)&server_addr,
sizeof(server_addr)) == -1) {
perror("failed to do the bind\n");
return -1;
}
/* listen for connect on sockets */
if (listen(listener, 10) == -1) {
perror("failed to listen on socket\n");
return -1;
}
/* add the listener to the master set */
FD_SET(listener, master);
/* keep track of biggest file descriptor */
fdmax = listener;
while (1) {
read_fds = master;
/* wait till socket descriptor is ready for the operation */
if (select(fdmax+1, read_fds, NULL, NULL, NULL) == -1) {
perror("failed to do select() on socket\n");
return -1;
}
/* Run through existing data connections looking for data to be
* read */
int cnt;
int *accept_fd = 0;
for (cnt=0; cnt<=fdmax; cnt++) {
if (cnt == listener) {
if (FD_ISSET(cnt, read_fds)) {
addrlen = sizeof(client_addr);
if ((newfd = accept(listener, (struct sockaddr*)&client_addr, &addrlen)) == -1) {
perror("failed to accept incoming connection\n");
} else {
fprintf(stdout, "Server: Connection from client [%s] on socket [%d]\n",
inet_ntoa(client_addr.sin_addr), newfd);
accept_fd = malloc(sizeof(int));
*accept_fd = newfd;
if ((res = pthread_create(&thread, NULL, data_processing_thread, (void*)accept_fd)) != 0) {
perror("Thread creation failed\n");
free(accept_fd);
}
}
}
continue;
}
}
}
return 1;
}
void *data_processing_thread(void *arg)
{
int nbytes;
int *recv_fd = (int*)arg;
char *buffer = malloc(sizeof(char)*256);
while(1) {
fprintf(stdout, "Server: Waiting for data from socket fd %d\n", *recv_fd);
/* receive incoming data from comm client */
if ((nbytes = recv(*recv_fd, buffer, sizeof(buffer), 0)) <= 0) {
if (nbytes != 0) {
perror("failed to receive\n");
}
break;
} else {
fprintf(stdout, "Data received: %s\n", buffer);
}
}
close(*recv_fd);
free(recv_fd);
pthread_exit(0);
}
Create two listening sockets using socket().
Bind both to respective address/port using bind().
Make both listen using listen().
Add both listening sockets to a properly initialised fd_set typed variable using FD_SET().
Pass the fd_set to a call to select()
Upon select()'s return check the reason and perform the appropriate action, typically
either calling accept() on one of the both listening sockets and add the accepted socket (as returned by accept()) to the fd_set,
or if it's an accepted socket that had triggered select() to return, then call read(), write() or close() on it. If close()ing the socket also remove it from the fd_set using FD_CLR().
Start over with step 5.
Important note: The steps above are a rough scheme, not mentioning all possible all traps, so it is absolutly necessary to also read the related man-pages for each step carefully, to understand what is happening.
you can bind 0.0.0.0 which means binding all interfaces.
you can't bind two interfaces using only one socket.
you should create a new socket, and bind ti to interface II.

Send an UDP packet and receive an ICMP response from router in C

I'm trying write a C program that sends an UDP packet to a given IP adress and waits for an ICMP response of a router telling that the time to live expired. It's kept very simple because I just want to understand the mechanism at first. What I need is someone checking my code giving feedback on what's wrong and what's missing. I'm very unexperienced at C-programming but I have to do it as an assignment - giving my best to understand it...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h>
// The packet length
#define PCKT_LEN 8192
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
int send, recv, resp;
int ttl = 1; // Time to live
char buffer[PCKT_LEN];
// Destination address
struct sockaddr_in dst;
// ICMP Response
struct msghdr icmp;
memset(buffer, 0, PCKT_LEN);
// Create a raw socket with UDP protocol
if ((send = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
printf("Could not process socket() [send].\n");
return EXIT_FAILURE;
}
// ICMP Socket
if ((recv = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
printf("Could not process socket() [recv].\n");
return EXIT_FAILURE;
}
dst.sin_family = AF_INET;
dst.sin_addr.s_addr = inet_addr("74.125.39.106");
dst.sin_port = htons(60001);
// Define time to life
if(setsockopt(send, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
{
printf("Could not process setsockopt().\n");
return EXIT_FAILURE;
}
if(sendto(send, buffer, sizeof(buffer), 0, (struct sockaddr *) &dst, sizeof(dst)) < 0)
{
printf("Could not process sendto().\n");
return EXIT_FAILURE;
}
if((resp = recvmsg(recv, (struct msghdr *) &icmp, IP_RECVERR|MSG_ERRQUEUE)) < 0 )
{
printf("Could not process recvmsg().\n");
return EXIT_FAILURE;
}
close(send);
close(recv);
return 0;
}
I keep receiving "Could not process recvmsg()." and I have no clue anymore what else to try. I'd like to receive an ICMP answer and read its senders IP-Address.
Looking forward to helpfull hints.
Best regards!
I normally use
recvfrom(serversock, buf, 100, 0, (struct sockaddr *)&rcv,&size);
printf("Received packet from %s:%d\nData: %s\n\n", inet_ntoa(rcv.sin_addr), ntohs(rcv.sin_port), buf);

Resources