2020/05/26

Linux shell to access tcp connection.

Open a new connection
1
exec FILE_DESCRIPTOR<>/dev/PROTOCOL/HOST/PORT
FILE_DESCRIPTOR: 0=stdin, 1=stdout, 2=stderr. So you can use numbers larger than 3.
PROTOCOL: tcp or udp
HOST: Host name or IP address.
PORT: Host listen port.


Send message
1
echo -e "MESSAGE" >&FILE_DESCRIPTOR
MESSAGE: The message which you want to send.
FILE_DESCRIPTOR: File descriptor when creating the connection..


Receive message
1
timeout SECOND cat <&FILE_DESCRIPTOR
SECOND: Wait SECOND seconds and then time out.
FILE_DESCRIPTOR: File descriptor when creating the connection..


Close connection
1
exec FILE_DESCRIPTOR<&-
FILE_DESCRIPTOR: File descriptor when creating the connection..


Example
1
2
3
4
5
6
7
8
9
exec 3<>/dev/tcp/192.168.5.250/1539
sleep 1
echo -e "test" >&3
timeout 5 cat <&3
sleep 1
echo -e "exit" >&3
timeout 5 cat <&3
sleep 1
exec 3<&-

[C] Simple daemon example with multiple connections


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#define PORT 1539
#define MAX_CLIENT 32

// connection information
struct connectInfo {
	int socket;
	int index;
};

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[MAX_CLIENT]={0};

// Each connection creates a pthread to handle communication.
void * sThread(void *arg)
{
	char message[64], retmsg[64];
	struct connectInfo *cInfo = (struct connectInfo *)arg;
	int nSocket = cInfo->socket;

	pthread_detach(pthread_self());
	int resume=1, i;
	struct timeval timeout;
	fd_set fds;
	
	FD_ZERO(&fds);
	FD_SET(nSocket, &fds);
	
	while (resume) {
		// reset timer
		timeout.tv_sec = 300;
		timeout.tv_usec = 0;
		
		// receive message with timeout control.
		i = select(nSocket+1, &fds, NULL, NULL, &timeout);
		if (0 == i) {
			printf("[%d] timeout\n", nSocket);
			resume = 0;
		} else if (-1 == i) {
			printf("[%d] got error\n", nSocket);
			resume = 0;
		} else {
			// The message still needs to be retrieved by recv.
			recv(nSocket , message , sizeof(message) , 0);
			printf("[%d] got message %s\n", nSocket, message);
			//pthread_mutex_lock(&lock);
			/*                         */
			//pthread_mutex_unlock(&lock);
			if (strncmp (message, "exit" , 4) == 0 ) {
				sprintf(retmsg, "bye");
				resume = 0;
			} else {
				sprintf(retmsg, "I got %s", message);
			}
			// Reply message to the other side.
			send(nSocket, retmsg, sizeof(retmsg), 0);
		}
	}
	// close connection
	close(nSocket);
	// release tid
	tid[cInfo->index] = 0;
	// exit pthread
	pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
	int sSocket, nSocket, i;
	struct sockaddr_in s_in;
	struct sockaddr_storage s_storage;
	socklen_t addr_size;
	struct connectInfo cInfo[MAX_CLIENT];
	
	sSocket = socket(PF_INET, SOCK_STREAM, 0);
	
	// Set daemon to listen on port 1539 to any address 
	s_in.sin_family = AF_INET;
	s_in.sin_port = htons(PORT);
	s_in.sin_addr.s_addr = htonl(INADDR_ANY);
	memset(s_in.sin_zero, '\0', sizeof s_in.sin_zero);
	bind(sSocket, (struct sockaddr *) &s_in, sizeof(s_in));

	// start listen.
	if(listen(sSocket, MAX_CLIENT)==0) {
		printf("Listening\n");
	} else {
		printf("Listen Fail\n");
		exit(-1);
	}

	i = 0;
	while (1) {
		addr_size = sizeof(s_storage);
		nSocket = accept(sSocket, (struct sockaddr *) &s_storage, &addr_size);
		if (-1 == nSocket) {	//accept return error
			continue;
		}

		// when got a new connection, find an empty tid to create a new pthread.
		for (i=0; i<MAX_CLIENT; i++) {
			if (0 == tid[i]) {
				cInfo.socket = nSocket;
				cInfo.index = i;
				if( pthread_create(&tid[i], NULL, sThread, (void*) &cInfo[i]) != 0 ) {
					printf("Failed to create thread\n");
				} else {
					i = MAX_CLIENT+1;
				}
			}
		}
		
		if (MAX_CLIENT == i) {
			printf("No more free thread.\n");
			close(nSocket);
		}
	}
}