ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I want to build a TCP socket function which based on a event application.
I almost finished all the function except a small problem.
Here is the problem, The client can connect my application call evtest through port 7046. After the connection is built, the evtest can send out the command string to the client.
But if the client closes the connection and my evtest will shut down also. It said that "Send, connection reset by peer."
What I really want my evtest can always active, the client side can always connect to my evtest even after close the connection.
To more clearly present what I want, I want the evtest application can always accept the outside connection and send out the command to them. Even the client break out connection, they can simply connect to my evtest application without disturb my evtest.
int fd, rd, i, j, k;
struct input_event ev[64];
int version;
unsigned short id[4];
unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
char name[256] = "Unknown";
int abs[5];
// Network parameters
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char *messageCommand; // A message pointer will pointer the command string
messageCommand = (char *)malloc(5 + 1 + 5 + 1 + 5 + 1 + 2);
char *testMessage="Send the test string out!";
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
// What port am I on
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
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);
}
/*
* In here, it starts to send the event to user
*/
if (argc < 2) {
printf("Usage: evtest /dev/input/eventX\n");
printf("Where X = input device number\n");
return 1;
}
for (i = 0; i < EV_MAX; i++) {
if (test_bit(i, bit[0])) {
printf(" Event type %d (%s)\n", i, events[i] ? events[i] : "?");
if (!i) continue;
ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
for (j = 0; j < KEY_MAX; j++) {
if (test_bit(j, bit[i])) {
printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
if (i == EV_ABS) {
ioctl(fd, EVIOCGABS(j), abs);
for (k = 0; k < 5; k++)
if ((k < 3) || abs[k])
printf(" %s %6d\n", absval[k], abs[k]);
}
}
}
}
}
printf("Wait for connection");
printf("Testing ... (interrupt to exit)\n");
//Setup a sending message destination, new_fd is the address where send to
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
Having read your description what immediately comes to mind is that you need to fork your server application.
You set up your server as a listening socket.
When a connection arrives you call fork to create a clone of the server process
The parent will close the connection and continue listening for more requests
The child will close the listening socket but retain and process the connection with the client.
That's the basic theory. For more do a google on: fork listening socket tutorial
Alternatively, you could run your server under inted (though doing it (the forking etc) yourself will be more efficient if you expect a lot of connections).
Thanks for the information.
I made it work now.
Thank you for graemef reminder. What I really Miss in the code, it is fork.
--------------------------------------------------------------------------------------
/*
* $RCSfile: evtest.c,v $
* Original Author...: Anthony Awtrey
* Version...........: $Revision: 1.1 $
* Last Modified By..: $Author: aawtrey $
* Last Modified.....: $Date: 2005/03/05 04:45:14 $
*
* Copyright 2005 I.D.E.A.L. Technology Corporation
* Based on event test example code Copyright (c) 1999-2000 Vojtech Pavlik
*
* Purpose:
* Report complete set of events from the /dev/input/event* devices
*
* NOTE: This program was modified to include all current event types,
* codes and values available from the 2.6.7 kernel's input.h file.
* A script called mkheader.pl was written to parse the contents of the
* input.h file to automate the process of creating the evtest.h file.
* This should make it easier to track future changes for the event
* device stream in the kernel.
*
* PEDANTIC BUILD INSTRUCTIONS:
* gcc -o evtest evtest.c
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
int fd, rd, i, j, k;
struct input_event ev[64];
int version;
unsigned short id[4];
unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
char name[256] = "Unknown";
int abs[5];
// Network parameters
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char *messageCommand; // A message pointer will pointer the command string
messageCommand = (char *)malloc(5 + 1 + 5 + 1 + 5 + 1 + 2); //set the memory
//char *testMessage="Send the test string out!";
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
// What port am I on
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
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);
}
/*
* In here, it starts to send the event to user
*/
if (argc < 2) {
printf("Usage: evtest /dev/input/eventX\n");
printf("Where X = input device number\n");
return 1;
}
for (i = 0; i < EV_MAX; i++) {
if (test_bit(i, bit[0])) {
printf(" Event type %d (%s)\n", i, events[i] ?events[i] : "?");
if (!i) continue;
ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
for (j = 0; j < KEY_MAX; j++) {
if (test_bit(j, bit[i])) {
printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
if (i == EV_ABS) {
ioctl(fd, EVIOCGABS(j), abs);
for (k = 0; k < 5; k++)
if ((k < 3) || abs[k])
printf(" %s %6d\n", absval[k], abs[k]);
}
}
}
}
}
#if 0
/*---Forever... ---*/
while (1)
{ int clientfd;
struct sockaddr_in client_addr;
socklen_t addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (!fork())
{
/*---Echo back anything sent---*/
while (send(clientfd, /*buffer*/"t", 2, 0) != -1)
;
exit(0);
}
/*---Close data connection---*/
close(clientfd);
}
#endif
int connected;
printf("Wait for connection\n");
printf("Testing ... (interrupt to exit)\n");
while(1) // connection accept loop
{
//Setup a sending message destination, new_fd is the address where send to
sin_size = sizeof(struct sockaddr_in);
printf("waiting for connection...\n");
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
pid_t pID = fork();
if (pID == 0)
{
printf("fork() child process\n");
// FORK START
close(sockfd); // sockfd is not needed in the child process
connected = 1;
while (connected) // data transfer loop
{
int sType=-1;
int sCode=-1;
int sValue=-1;
for (i = 0; i < rd / sizeof(struct input_event); i++)
{
printf("%d ", i);
if (ev[i].type == EV_SYN)
{
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?",
ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
ev[i].value);
printf("Event: time %ld.%06ld, -------------- %s ------------\n",
ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" );
}
else
{
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?",
ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
ev[i].value);
//Put into parameters
sType=ev[i].type;
sCode=ev[i].code;
sValue=ev[i].value;
sprintf(messageCommand, "%hd,%hd,%hd,\n", sType, sCode, sValue);
if (send(new_fd, messageCommand, strlen(messageCommand), 0) == -1)
{
printf("disconnected\n");
connected = 0;
break;
}
}// end else
} // end for loop
} //end while data transfer loop
Thanks for the information.
I made it work now.
Thank you for graemef reminder. What I really Miss in the code, it is fork.
--------------------------------------------------------------------------------------
/*
* $RCSfile: evtest.c,v $
* Original Author...: Anthony Awtrey
* Version...........: $Revision: 1.1 $
* Last Modified By..: $Author: aawtrey $
* Last Modified.....: $Date: 2005/03/05 04:45:14 $
*
* Copyright 2005 I.D.E.A.L. Technology Corporation
* Based on event test example code Copyright (c) 1999-2000 Vojtech Pavlik
*
* Purpose:
* Report complete set of events from the /dev/input/event* devices
*
* NOTE: This program was modified to include all current event types,
* codes and values available from the 2.6.7 kernel's input.h file.
* A script called mkheader.pl was written to parse the contents of the
* input.h file to automate the process of creating the evtest.h file.
* This should make it easier to track future changes for the event
* device stream in the kernel.
*
* PEDANTIC BUILD INSTRUCTIONS:
* gcc -o evtest evtest.c
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
int fd, rd, i, j, k;
struct input_event ev[64];
int version;
unsigned short id[4];
unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
char name[256] = "Unknown";
int abs[5];
// Network parameters
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char *messageCommand; // A message pointer will pointer the command string
messageCommand = (char *)malloc(5 + 1 + 5 + 1 + 5 + 1 + 2); //set the memory
//char *testMessage="Send the test string out!";
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
// What port am I on
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
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);
}
/*
* In here, it starts to send the event to user
*/
if (argc < 2) {
printf("Usage: evtest /dev/input/eventX\n");
printf("Where X = input device number\n");
return 1;
}
for (i = 0; i < EV_MAX; i++) {
if (test_bit(i, bit[0])) {
printf(" Event type %d (%s)\n", i, events[i] ?events[i] : "?");
if (!i) continue;
ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
for (j = 0; j < KEY_MAX; j++) {
if (test_bit(j, bit[i])) {
printf(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
if (i == EV_ABS) {
ioctl(fd, EVIOCGABS(j), abs);
for (k = 0; k < 5; k++)
if ((k < 3) || abs[k])
printf(" %s %6d\n", absval[k], abs[k]);
}
}
}
}
}
#if 0
/*---Forever... ---*/
while (1)
{ int clientfd;
struct sockaddr_in client_addr;
socklen_t addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (!fork())
{
/*---Echo back anything sent---*/
while (send(clientfd, /*buffer*/"t", 2, 0) != -1)
;
exit(0);
}
/*---Close data connection---*/
close(clientfd);
}
#endif
int connected;
printf("Wait for connection\n");
printf("Testing ... (interrupt to exit)\n");
while(1) // connection accept loop
{
//Setup a sending message destination, new_fd is the address where send to
sin_size = sizeof(struct sockaddr_in);
printf("waiting for connection...\n");
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
pid_t pID = fork();
if (pID == 0)
{
printf("fork() child process\n");
// FORK START
close(sockfd); // sockfd is not needed in the child process
connected = 1;
while (connected) // data transfer loop
{
int sType=-1;
int sCode=-1;
int sValue=-1;
for (i = 0; i < rd / sizeof(struct input_event); i++)
{
printf("%d ", i);
if (ev[i].type == EV_SYN)
{
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?",
ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
ev[i].value);
printf("Event: time %ld.%06ld, -------------- %s ------------\n",
ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" );
}
else
{
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?",
ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
ev[i].value);
//Put into parameters
sType=ev[i].type;
sCode=ev[i].code;
sValue=ev[i].value;
sprintf(messageCommand, "%hd,%hd,%hd,\n", sType, sCode, sValue);
if (send(new_fd, messageCommand, strlen(messageCommand), 0) == -1)
{
printf("disconnected\n");
connected = 0;
break;
}
}// end else
} // end for loop
} //end while data transfer loop
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.