Hi I'm trying to write a client application which will try to connect a remote server. If it can not connect to the server, it will try once again after 5 seconds. If the socket is closed somehow, it will try to connect once again.
I'm getting an error like connect: Transport endpoint is already connected
What could be the problem ?
static void sig_chld(int signo)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
return;
}
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
pid_t childpid;
struct hostent *he;
struct sockaddr_in their_addr; /* connector's address information */
if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info */
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
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);
bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */
for ( ; ; ) {
while (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
sleep(5);
}
if ( (childpid = fork()) == 0)
{ /* child process */
while(1)
{
if (send(sockfd, "Hello, world!\n", 14, 0) == -1)
{
perror("send");
}
sleep(3);
}
close(sockfd);
}
}
return 0;
}
You can't reconnect a socket once you have even tried to connect it before, even if it failed. You have to close it and create a new one.
Related
I have used the linux part of code in windows to establish RDB communication. Though the socket opening is successful, I am unable to bind the socket with the IP Address defined. Is there any limitation between Linux and Windows over socket?
Here's my code,
SOCKET sock;
SOCKET sClient;
struct sockaddr_in server;
char szServer128; // Server to connect to
char szBuffer204800; // allocate on heap
sClient = udpsock_open(&server, szServer, DEFAULT_RX_PORT);
int udpsock_open(struct sockaddr_in *psa, char *ipv4, uint16_t port) {
WSADATA wsaData;
int opt;
int domain = AF_INET;
int type = SOCK_DGRAM;
int proto = IPPROTO_UDP;
sClient = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (sClient 0)
printf(" WSAStartup Successful %I64d\n", sClient);
else
printf("Failed. Error Code : %d\n", WSAGetLastError());
// Prepare a socket to listen for connections
if ((sock = WSASocket(domain, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
else
{
printf("WSASocket() is OK!\n");
}
if (sock < 0)
{
//rtos_log ( LOG_ERR, "Failed to open socket %m" );
printf("Failed to open socket %I64d\n", sock);
return -1;
}
set_reuse(sock);
memset(psa, 0x00, sizeof(struct sockaddr_in));
psa->sin_family = domain;
psa->sin_port = htons(port);
psa->sin_addr.s_addr = inet_addr(ipv4);
if (bind(sock, ( struct sockaddr *)psa, sizeof(struct sockaddr_in)) < 0)
{
printf("Failed to bind socket Error: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -4;
}
opt = 1;
char buf[2048];
DWORD dwBytesRet;
//ioctlsocket(sock, FIONBIO, &opt)
if (WSAIoctl(sock, SIO_ADDRESS_LIST_QUERY,NULL,0, buf,2048, &dwBytesRet,NULL,NULL) == SOCKET_ERROR)
{
printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
return 1;
}
else
{
printf("ioctlsocket() is OK!\n");
}
return sock;
}
I create a TCP server socket that listens to connect() requests and accept() them. After accepting a client socket receives data from it. I want recv() function to block with a timeout, but it seems to be non-blocking.
I have achieved the client to be in blocking mode when receiving response from the server, but it does not seem to work the same with the server side.
Below I copy-paste the server side that I want to receive data in blocking mode:
int clientSocket = accept(_serverSocket, (struct sockaddr *)NULL, NULL);
if (clientSocket < 0)
return -1;
// set TIMEOUT option to server socket
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500 * 1000;
int sockOptRet = setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
struct linger sl;
sl.l_onoff = 1; /* non-zero value enables linger option in kernel */
sl.l_linger = 0; /* timeout interval in seconds */
setsockopt(clientSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
char _rcvBuffer[sizeof(can_frame)];
int numBytesRcv = recv(clientSocket, _rcvBuffer, sizeof(can_frame), 0);
I have also tried it with MSG_WAITALL flag but it does not change anything...
Your code should clearly block, but your timeout of 0.5s doesn't do showing it justice.
If you increase the timeout to something more conspicuous such as 2s and graft the code onto, e.g., beej's tpc server template, you get something like:
/*
** server.c -- a stream socket server demo
*/
#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>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s)
{
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &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("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
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("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
// set TIMEOUT option to server socket
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0 * 500 * 1000;
int sockOptRet = setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
struct linger sl;
sl.l_onoff = 1; /* non-zero value enables linger option in kernel */
sl.l_linger = 0; /* timeout interval in seconds */
setsockopt(new_fd, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));
char can_frame[1024];
char _rcvBuffer[sizeof(can_frame)];
int numBytesRcv = recv(new_fd, _rcvBuffer, sizeof(can_frame), 0);
if (send(new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
Now if your run this and then do:
nc localhost 3490
without typing a line to send, there should be a distinct 2-second wait
before the server gives up on you, indicating that the recv is indeed blocking.
I use netlink to receive an interrupt number from kernel. The application in user space uses libevent to handle TCP/IP request and netlink message. Does libevent support Linux netlink socket? I will appreciate for a simple example.
Yes, libevent supports netlink socket.
There is https://github.com/libevent/libevent/blob/master/sample/hello-world.c, it is modified below to listen to netlink socket.
The basic example listens to Linux network interface creation/deletion and can be executed with sudo to gain privilege needed. It listens to same events as ip monitor link.
Another example of listening to RAW sockets with libevent is here https://github.com/bodgit/libevent-natpmp/blob/master/natpmp.c.
static void link_recvmsg(int fd, short event, void *arg)
{
char buf[NLMSG_SPACE(BUF_SIZE)] = {0};
socklen_t socklen;
struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)};
struct sockaddr addr;
memset(&addr, 0, sizeof(struct sockaddr));
if (!fd || -1 == fd)
return;
int status = getsockname(fd, &addr, &socklen);
if(-1 == status)
return;
struct msghdr mh = {.msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1,
.msg_flags = 0, .msg_name = &addr, .msg_namelen = sizeof(struct sockaddr)};
status = recvmsg(fd, &mh, 0);
if ((-1 == status) && ((EINTR == errno) || (EAGAIN == errno)))
return;
if(-1 == status)
return;
if ((mh.msg_flags & MSG_TRUNC) == MSG_TRUNC)
return;
if ((mh.msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
return;
for (const struct nlmsghdr *h = (struct nlmsghdr *)buf; NLMSG_OK(h, status); h = NLMSG_NEXT(h, status)) {
switch (h->nlmsg_type) {
case RTM_NEWLINK:
fprintf(stderr, "got RTM_NEWLINK\n");
break;
case RTM_DELLINK:
fprintf(stderr, "got RTM_DELLINK\n");
break;
default:
fprintf(stderr, "unexpected case in swtch statement\n");
break;
}
}
}
int main(int argc, char **argv)
{
/* some init code here */
/* NETLINK socket */
int status;
int buf_size = BUF_SIZE;
struct sockaddr_nl src_addr;
int socket_nl = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
if(-1 == socket_nl) return -1;
memset(&src_addr, 0, sizeof(struct sockaddr_nl));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups |= RTNLGRP_LINK;
status = setsockopt(socket_nl, SOL_SOCKET, SO_RCVBUF,
&buf_size, sizeof(buf_size));
if(-1 == status) return -1;
status = bind(socket_nl, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl));
if(status < 0) return -1;
static struct event nl_ev;
event_set(&nl_ev, socket_nl, EV_READ|EV_PERSIST, link_recvmsg,
NULL);
if (base) {
event_base_set(base, &nl_ev);
}
event_add(&nl_ev, NULL);
/* some other code, dispatch event and deinit */
}
I have the following codes..
server.c
#include <stdio.h>
#include "./../linux.h"
#include "./tcp.h"
#include <pthread.h>
static int clients = 0;
static int* memptr = NULL;
void serve(void*);
int* push(int* memptr, int nsfd) {
clients++;
if (clients == 1)
memptr = (int*)malloc(sizeof(int) * clients);
else
memptr = (int*)realloc(memptr, sizeof(int) * clients);
memptr[clients - 1] = nsfd;
return memptr;
}
int main(int argc, char** argv) {
pthread_t thread[2];
int threadCount = 0;
if (argc != 3){
printf("\nUsage: ./server port_number maximum_clients\n");
return 1;
}
static struct sockaddr_in sock, sock_client;
int len, new_sock_fd;
int sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1){
perror("socket");
exit(1);
}
sock.sin_family = PF_INET;
sock.sin_port = htons(atoi(argv[1]));
sock.sin_addr.s_addr = inet_addr("0.0.0.0");
len = sizeof(sock);
if ( bind(sock_fd, (struct sockaddr *)&sock, len) == -1){
perror("bind");
exit(1);
}
if ( listen(sock_fd, atoi(argv[2])) == -1){
perror("listen");
exit(1);
}
while(1) {
new_sock_fd = accept(sock_fd, (struct sockaddr *)&sock_client, (socklen_t *)&len);
memptr = push(memptr, new_sock_fd);
if (new_sock_fd == -1){
perror("accept");
exit(1);
}
pthread_create(&(thread[threadCount]), NULL, (void*)&serve, (void *)&new_sock_fd);
pthread_join(thread[threadCount++], NULL);
printf("threadCount = %d\n", threadCount);
sleep(1);
}
return 0;
}
void serve(void* fd){
int* new_sock_fd = (int*)fd;
Packet packet;
while(1){
bzero(&packet, sizeof(packet));
read(*new_sock_fd , &packet, sizeof(packet));
printf("%d\n", *new_sock_fd);
//printf("recipientId = %d\n", packet.recipientId);
// printf("message = %s\n", packet.data);
write(memptr[packet.recipientId - 1], packet.data, 1024);
}
pthread_exit(0);
}
and the tcp.h looks like
#ifndef __TCP_H__
# define __TCP_H__
typedef struct {
int recipientId; // this is the reciever ID
char data[1024]; // this is the main data part
}Packet;
#endif /* __TCP_H__ */
and each client.h looks like this
#include <stdio.h>
#include "./../linux.h"
#include "./tcp.h"
#include <pthread.h>
void print(void);
void scan(void);
int sock_fd;
int main(int argc, char** argv) {
if (argc != 3){
printf("\nUsage: ./client port_number server_ip\n");
return 1;
}
static struct sockaddr_in sock;
int len;
pthread_t thread1, thread2;
sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1){
perror("socket");
exit(1);
}
sock.sin_family = PF_INET;
sock.sin_port = htons(atoi(argv[1]));
sock.sin_addr.s_addr = inet_addr(argv[2]);
len = sizeof(sock);
if ( connect(sock_fd, (struct sockaddr *)&sock , len) == -1 ){
perror("connect");
exit(1);
}
pthread_create(&thread1, NULL, (void*)&print, NULL);
pthread_create(&thread2, NULL, (void*)&scan, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
void print(){
char messege[1024];
while(1){
if (read(sock_fd, messege, 1024) == -1){
perror("read");
return;
}
printf("messege = %s\n", messege);
}
pthread_exit(0);
}
void scan(void){
Packet packet;
while(1){
printf("Enter the reciver ID: ");
scanf("%d", &packet.recipientId);
printf("Enter the data: ");
scanf("%s", packet.data);
if ( write(sock_fd, &packet, sizeof(packet)) == -1) {
perror("read");
return;
}
}
pthread_exit(0);
}
Now the problems are
when I am running the server & the in 2 terminals, 2 clients after each client is accepted threadCount should be printed at the server end but it is not printing. It means the execution stops/skips after the first pthread_join but WHY ??
After connecting two threads, when I sent the data from 1st client to the 1st client itself, it works but not from the 1st client to the 2nd client..rather it is sending to the server terminal window. WHY ??
When sent from the second client nothing works ( sending itself or client 1)..WHY??
Please help..And thanks for patiently reading all the codes above.
TCP is a byte stream protocol, not a message protocol. You are calling TCP functions and expecting them to send or receive messages. They don't. If you want to send or receive messages, you have to implement a message protocol, write functions that send and receive messages, and then call those functions.
if (read(sock_fd, messege, 1024) == -1){
perror("read");
return;
}
printf("messege = %s\n", messege);
This call to printf is a disaster. The %s format specifier is for C-style strings, not arbitrary chunks of bytes received from a byte stream. For the most obvious way to see how bad this is, consider this --- how should printf decide how many bytes to print? You threw away the value read returned after you compared it to -1, so you have no idea how many bytes you received.
I'm sure there are other issues with your code, but the fact that the fundamental design is broken makes it not worth fixing those issues. Instead, design a message protocol and implement that.
I use multuple thread to receive data from one socket. they all can receive the same data. I want to know when the data will be taken away from recv buffer? Why does not one thread receive the next data when former thread read former data.
pthread_create(&(ntid[i]), NULL, find_host, (void *)&start_addr);
int find_host(void * arg)
{
int sockfd;
unsigned long ip ;
tv.tv_sec = 0;
tv.tv_usec = 100000;
struct sockaddr_in from;
char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
ip = *(unsigned long *)arg;
struct sockaddr_in present_addr;
if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
{
perror("socket error");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) );
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0){
printf("socket option SO_RCVTIMEO not support\n");
return;
}
bzero(&present_addr,sizeof(present_addr));
present_addr.sin_family=AF_INET;
present_addr.sin_addr.s_addr = htonl(ip);
pthread_mutex_unlock(&lock);
printf("PING (%s): %d bytes data in ICMP packets.\n",
inet_ntoa(present_addr.sin_addr),ICMP_DATA_LEN);
send_packet(sockfd, sendpacket, present_addr);
recv_packet(sockfd, recvpacket, from);
close(sockfd);
}
void recv_packet(int sockfd, char * recvpacket, struct sockaddr_in from)
{ int n,from_len;
extern int errno;
int nreceived = 0;
struct timeval recv_time;
from_len = sizeof(from);
while (nreceived < MAX_SEND_TIMES)
{
if((n=recvfrom(sockfd,recvpacket, PACKET_SIZE, 0,
(struct sockaddr *)&from,&from_len)) <0)
{
if(errno == EWOULDBLOCK || errno== EAGAIN )
{
printf("recvfrom Timeout!!!!\n");
pthread_exit(NULL);
}
}
gettimeofday(&recv_time,NULL);
if (1 == unpack(recv_time, recvpacket, n, from))
{
printf(" find %u\n", (unsigned short)pthread_self());
nreceived++;
}
else
printf(" not find\n");
}
}