I created a simple TCP server listening on 8080 port that sends a message to the client once a connection is established. Here's the code.
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)
int main(int argc, char* argv[]) {
WSADATA wsa;
SOCKET s, new_socket;
int c;
int ret;
struct sockaddr_in server, client;
char* message = "Thank you for connecting to us but i got to go\n";
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("Failed to initialize Winsock : %d", WSAGetLastError());
return 1;
}
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
printf("Error creating socket : %d", WSAGetLastError());
}
server.sin_family = AF_INET;
server.sin_port = htons(8080);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Error binding socket : %d\n", WSAGetLastError());
exit(EXIT_FAILURE);
}
listen(s, 3);
puts("Listening for incoming connection\n");
c = sizeof(struct sockaddr_in);
while (new_socket = accept(s, (struct sockaddr*)&client, &c) != INVALID_SOCKET) {
puts("Connection established\n");
send(new_socket, message, strlen(message), 0);
}
if (new_socket == INVALID_SOCKET) {
printf("Connection failed : %d", WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
When I'm running this, the server runs just fine. I open another terminal and open telnet and try to connect to the server on 8080 port. This is the client side terminal.
Welcome to Microsoft Telnet Client
Escape Character is 'CTRL+]'
Microsoft Telnet> open localhost 8080
Connecting To localhost...
And this is the server side.
Listening for incoming connection
Connection established
But even after server says that a connection is established, the client side stays at "Connecting to localhost". I send the message "Thank you for connecting to us but i got to go\n" but it doesn't show on the client side. what can possibly be wrong?
As it appears, it was a silly mistake.
while (new_socket = accept(s, (struct sockaddr*)&client, &c) != INVALID_SOCKET)
Since I didn't put another bracket over the new_socket = accept(s, (struct sockaddr*)&client, &c after initializing new_socket, the inequality was being applied on the accept function return.
The correct syntax would be
while ((new_socket = accept(s, (struct sockaddr*)&client, &c)) != INVALID_SOCKET)
Related
Suppose I have a TCP Server(A) listening on port 8001.
Now, I want to open a TCP Socket to Server(B) from Server(A) using local port 8001. So that, Server(B) will see connection from Server(A) from port 8001.
Is it possible ? Can I use a port for outgoing connection that's already used for listening incoming connections.
You can do that: socket followed by setsockopt(SO_REUSEPORT) and then bind.
man socket(7):
SO_REUSEPORT (since Linux 3.9)
Permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address. This option must be set on each socket (including the first socket) prior to calling bind(2) on the socket. To prevent port hijacking, all of the processes binding to the same address must have the same effective UID. This option can be employed with both TCP and UDP sockets.
Here is a working example that has two sockets bound to the same address and port 127.0.0.1:2222. One socket is a listening server socket, another is a client successfully making a connection to 127.0.0.1:22 (ssh):
#include <thread>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <err.h>
#include <unistd.h>
int socket_and_bind() {
int s = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == s)
err(EXIT_FAILURE, "socket");
int flag = 1;
if(-1 == setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof flag))
err(EXIT_FAILURE, "setsockopt(SO_REUSEPORT)");
sockaddr_in sa = {};
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa.sin_port = htons(2222);
sa.sin_family = AF_INET;
if(-1 == bind(s, reinterpret_cast<sockaddr*>(&sa), sizeof sa))
err(EXIT_FAILURE, "bind");
return s;
}
void server(int s) {
int c = accept(s, nullptr, nullptr);
if(-1 == c)
err(EXIT_FAILURE, "accept");
close(c);
}
void client(int s) {
sockaddr_in sa = {};
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa.sin_port = htons(22);
sa.sin_family = AF_INET;
if(-1 == connect(s, reinterpret_cast<sockaddr*>(&sa), sizeof sa))
err(EXIT_FAILURE, "connect");
char buf;
if(1 != recv(s, &buf, sizeof buf, 0))
err(EXIT_FAILURE, "recv");
printf("connected\n");
}
int main() {
int s1 = socket_and_bind();
if(-1 == listen(s1, 1))
err(EXIT_FAILURE, "listen");
int s2 = socket_and_bind();
std::thread t1(server, s1);
std::thread t2(client, s2);
t2.join();
t1.detach();
return EXIT_SUCCESS;
}
One thing that is broken in Linux is connecting from an addr:port to the same:addr port.
I use buildroot cross toolchain to compile Raspberry application from my computer (Ubuntu X86).
I'm developping a TCP serveur that allows a connection on 5003 (0x138B) TCP port number. When I'm start the server, that's right but my server wait a connection on 35603 (0x8B13) TCP port number (check with netstat -a).
It seems to be an endianness problem but I don't know how to resolve.
Can you help me please?
Thanks.
thanks for your answer.
I agree it's very strange. I don't think the code is the problem. It's working well on other platform.
Please find the code below:
/*Create the server */
int CreateServeur (unsigned short port, int *sock_srv, int nb_connect)
{
int l_ret = -1;
struct sockaddr_in l_srv_addr;
/* address initialisation */
printf("creation serveur port %i\n", port);
memset ((char*) &l_srv_addr,0, sizeof (struct sockaddr_in));
l_srv_addr.sin_family = PF_INET;
l_srv_addr.sin_port = port;
l_srv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
/* main socket creation */
if ((*sock_srv = socket (PF_INET, SOCK_STREAM, 0)) <= 0)
{
printf("server socket creation error");
}
else
{
if (bind (*sock_srv, (struct sockaddr *) &l_srv_addr, sizeof (struct sockaddr_in)) == -1)
{
close (*sock_srv);
printf("bind socket error");
}
else
{
if (listen (*sock_srv, nb_connect) == ERROR)
{
close (*sock_srv);
printf("listen socket error");
}
else
{
l_ret = 0;
}
}
}
return (l_ret);
}
This function doesn't return any error. The first log (printf("creation serveur port %i\n", port);) display the good port (5003) but the server wait connexion on port 35603 (netstat -a).
If it's not a endianness problem, I don't understand.
I need some serious help here. I have to make a TCP Server Client. When the Client connects to server using a three stage handshake. Afterwards, while the Client is running in the terminal, the user enters Linux shell commands like xinput list, ls -1, etc — something that uses standard output. The server accepts the commands and uses system() (in a fork() in an infinite loop) to run the commands and the standard output is redirected to the client, where the client prints out each line.
Afterward the server sends a completion signal of "\377\n". In which the client goes back to the command prompt asking for a new command and closes its connection and exit()'s when inputting "quit".
I know that you have to dup2() both the STDOUT_FILENO and STDERR_FILENO to the client's file descriptor {dup2(client_FD, STDOUT_FILENO). Everything works except when it comes for the client to retrieve system()'s stdout and printing it out... all I get is a blank line with a blinking cursor (client waiting on stdin). I tried all kinds of different routes to no avail... If anyone can help out I would greatly appreciate it
TCP SERVER CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
//Prototype
void handle_client(int connect_fd);
int main()
{
int server_sockfd, client_sockfd;
socklen_t server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
/* Create a connection queue, ignore child exit details and wait for clients. */
listen(server_sockfd, 10);
signal(SIGCHLD, SIG_IGN);
while(1) {
printf("server waiting\n");
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
if(fork() == 0)
handle_client(client_sockfd);
else
close(client_sockfd);
}
}
void handle_client(int connect_fd) {
const char* remsh = "<remsh>\n";
const char* ready = "<ready>\n";
const char* ok = "<ok>\n";
const char* command = "<command>\n";
const char* complete = "<\377\n";
const char* shared_secret = "<shapoopi>\n";
static char server_msg[201];
static char client_msg[201];
static char commands[201];
int sys_return;
//memset client_msg, server_msg, commands
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(client_msg));
memset(&commands, 0, sizeof(commands));
//read remsh from client
read(connect_fd, &client_msg, 200);
//check remsh validity from client
if(strcmp(client_msg, remsh) != 0) {
errno++;
perror("Error Establishing Handshake");
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write remsh to client
write(connect_fd, remsh, strlen(remsh));
//read shared_secret from client
read(connect_fd, &client_msg, 200);
//check shared_secret validity from client
if(strcmp(client_msg, shared_secret) != 0) {
errno++;
perror("Invalid Security Passphrase");
write(connect_fd, "no", 2);
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write ok to client
write(connect_fd, ok, strlen(ok));
// dup2 STDOUT_FILENO <= client fd, STDERR_FILENO <= client fd
dup2(connect_fd, STDOUT_FILENO);
dup2(connect_fd, STDERR_FILENO);
//begin while... while read (client_msg) from server and >0
while(read(connect_fd, &client_msg, 200) > 0) {
//check command validity from client
if(strcmp(client_msg, command) != 0) {
errno++;
perror("Error, unable to retrieve data");
close(connect_fd);
exit(1);
}
//memset client_msg
memset(&client_msg, 0, sizeof(client_msg));
//write ready to client
write(connect_fd, ready, strlen(ready));
//read commands from client
read(connect_fd, &commands, 200);
//run commands using system( )
sys_return = system(commands);
//check success of system( )
if(sys_return < 0) {
perror("Invalid Commands");
errno++;
}
//memset commands
memset(commands, 0, sizeof(commands));
//write complete to client
write(connect_fd, complete, sizeof(complete));
}
}
TCP CLIENT CODE
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "readline.c"
int main(int argc, char *argv[])
{
int sockfd;
int len;
struct sockaddr_in address;
int result;
const char* remsh = "<remsh>\n";
const char* ready = "<ready>\n";
const char* ok = "<ok>\n";
const char* command = "<command>\n";
const char* complete = "<\377\n";
const char* shared_secret = "<shapoopi>\n";
static char server_msg[201];
static char client_msg[201];
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(server_msg));
/* Create a socket for the client. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server. */
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(argv[1]);
address.sin_port = htons(9734);
len = sizeof(address);
/* Now connect our socket to the server's socket. */
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == -1) {
perror("ACCESS DENIED");
exit(1);
}
//write remsh to server
write(sockfd, remsh, strlen(remsh));
//read remsh from server
read(sockfd, &server_msg, 200);
//check remsh validity from server
if(strcmp(server_msg, remsh) != 0) {
errno++;
perror("Error Establishing Initial Handshake");
close(sockfd);
exit(1);
}
//memset server_msg
memset(&server_msg, 0, sizeof(server_msg));
//write shared secret text to server
write(sockfd, shared_secret, strlen(shared_secret));
//read ok from server
read(sockfd, &server_msg, 200);
//check ok velidity from server
if(strcmp(server_msg, ok) != 0 ) {
errno++;
perror("Incorrect security phrase");
close(sockfd);
exit(1);
}
//? dup2 STDIN_FILENO = server socket fd?
//dup2(sockfd, STDIN_FILENO);
//begin while(1)///////////////////////////////////////
while(1){
//memset both msg arrays
memset(&client_msg, 0, sizeof(client_msg));
memset(&server_msg, 0, sizeof(server_msg));
//print Enter Command, scan input, fflush to stdout
printf("<<Enter Command>> ");
scanf("%s", client_msg);
fflush(stdout);
//check quit input, if true close and exit successfully
if(strcmp(client_msg, "quit") == 0) {
printf("Exiting\n");
close(sockfd);
exit(EXIT_SUCCESS);
}
//write command to server
write(sockfd, command, strlen(command));
//read ready from server
read(sockfd, &server_msg, 200);
//check ready validity from server
if(strcmp(server_msg, ready) != 0) {
errno++;
perror("Failed Server Communications");
close(sockfd);
exit(1);
}
//memset server_msg
memset(&server_msg, 0, sizeof(server_msg));
//begin looping and retrieving from stdin,
//break loop at EOF or complete
while((read(sockfd, server_msg, 200) != 0) && (strcmp(server_msg, complete) != 0)) {
//while((fgets(server_msg, 4096, stdin) != EOF) || (strcmp(server_msg, complete) == 0)) {
printf("%s", server_msg);
memset(&server_msg, 0, sizeof(server_msg));
}
}
}
The output of subprocess, spawned by system(), is not connected to the calling parent process.
Try popen().
In the server, the error exits from handle_client() carefully call close(connect_fd); but the ordinary exit does not. This means that the server does not close the connection to the client, so the client waits for the server to disconnect. This is why you see the code hanging.
I am trying to write a TCP Echo program that should open a TCP server socket, accept at least 1 connection, and echo back any data received. At minimum, this program should launch and run on a specified port (exe: port 4444". Ideally, it would ask for a port number (from command line, command line parameter, or config file), attempt to open on that port, and report if errors occurred.
The program is supposed to be tested using the telnet command from windows or Linux, or any terminal emulator in any OS. The use connects to the running program using Telnet or Hyperterminal. Anything that gets typed in should echo back immediately.
So far I have the following:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#define MAXCONNECTING 1000 //Max connection requests
#define BUFFERSIZE 128 //limits data sent per loop
#define ECHOPORT 4444
//Error checking function
//Will be called multiple times to check for errors throughout the code
void ERR(char *ERROR) {
perror(ERROR);
exit(1);
}
/****************************************************************************
* Handles the connection. Receive/Send data from/to client
****************************************************************************/
void ClientHandle(int sock) {
char buffer[BUFFERSIZE];
int received = -1;
//receive the data
if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
ERR("Failed to receive message from client");
}
//send data and check for more incoming data
while (received > 0) {
if (send(sock, buffer, received, 0) != received) {
ERR("Failed to send data to client");
}
if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
ERR("Failed to receive additional data from client");
}
}
close(sock);
}
int main(int argc, char *argv[]) {
/****************************************************************************
* Get port number from command line and set to default port
****************************************************************************/
char *endptr;
short int port;
if (argc == 2) {
port = strtol(argv[1], &endptr, 0);
if (*endptr) {
fprintf(stderr, "EchoServer: Invalid Port Number.\n");
exit(EXIT_FAILURE);
}
} else if (argc < 2) {
port = ECHOPORT; //port 4444
} else {
fprintf(stderr, "EchoServer: Invalid arguments.\n");
exit(EXIT_FAILURE);
}
/****************************************************************************
* Server Configuration. Creating the socket
****************************************************************************/
int serversock, clientsock;
struct sockaddr_in echoserver, echoclient;
if (argc != 2) {
fprintf(stderr, "USING: echoserver Port: 4444\n");
exit(1);
}
//Creating the TCP socket
if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
ERR("Failed to create socket");
}
//Constructing the server sockaddr_in structure
memset(&echoserver, 0, sizeof(echoserver)); //clear struct
echoserver.sin_family = AF_INET; //internet ip
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); //listen to any ip address
echoserver.sin_port = htons(atoi(argv[1])); //server port
/*****************************************************************************
* Bind and Listen
*****************************************************************************/
if (bind(serversock, (struct sockaddr *) &echoserver, sizeof (echoserver)) < 0) {
ERR("Failed to bind the server socket");
}
if (listen(serversock, MAXCONNECTING) < 0) {
ERR("Failed to listen on server socket");
}
/*****************************************************************************
* Accepting the transmission
*****************************************************************************/
while (1) {
unsigned int clientleng = sizeof (echoclient);
if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientleng)) < 0) {
ERR("Failed to accept connection from client");
}
fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
ClientHandle(clientsock);
}
return (0);
}
/*****************************************************************************************/
Can anyone see where I have went wrong? I can find the program in terminal using the command: g++ EchoServer.cpp -0 EchoServer and then followed by: ./EchoServer
The ouput only gives me:
USING: echoserver Port: 4444
I am trying to telnet to it, but I am very new at this stuff. Please help!!
Assuming that you have the contents of the textbox above in a file called EchoServer.cpp in the current directory, you can run the following code to demonstrate it working:
g++ EchoServer.cpp -o EchoServer
After it compiles, you will have an executable file called EchoServer in the same directory.
If you just call it, You will receive the cryptic message below, which means that to use the executable, you will have to tell it which port number to use.
USING: echoserver Port 4444
To demonstrate it working, we are going to put the process in the background. To do this, we use an ampersand (&) to turn it into a job.
EchoServer 4444 &
This should return a job number, and a process identifier (yours will be different), thus:
[1] 53912
You can see that it is running using the jobs command:
[1]+ Running ./EchoServer 4444 &
You can now telnet to this to see that it is working:
telnet localhost 4444
You should see:
Trying 127.0.0.1...
Client connected: 127.0.0.1
Connected to localhost.
Escape character is '^]'.
Anything you type after this will be sent back to you when you press enter or return. Try typing Hello and pressing return.
Once you are done, you can press and hold the control key and then the close square bracket key (you may have to press return afterwards). This will bring you out into a telnet prompt, and you should type quit to leave.
To close off the EchoServer executable, you can bring the job back to the foreground and stop it with a Control-C keypress. Assuming that your job was 1 (you can run jobs again to check the number), you can run the following command to bring it back to the foreground:
fg 1
You are now effectively in the EchoServer process, and pressing Control-C will end it.
That's it! You're done. You have successfully demonstrated the program working.
We need some help with a TCP client server code. The client timesout from its connect call and the server does not return from accept. Here's the strace.
strace -p 7167 -p 7168 -p 7297
Process 7167 attached - interrupt to quit
Process 7168 attached - interrupt to quit
Process 7297 attached - interrupt to quit
[pid 7167] accept(4, <unfinished ...>
[pid 7168] accept(4, <unfinished ...>
[pid 7297] connect(3, {sa_family=AF_INET, sin_port=htons(24465), sin_addr=inet_addr("215.47.142.168")}, 16
We rebooted the system but the problem persists even immediately after reboot.
Could it be a SYN Flood problem. How do we deal with such connections? Also, do the half made connections queue up in the listen queue(argument 2 of listen call) and stop any further accepts from any client OR does the TCP some how blocks that particular client only.
Here's the code...
client.all this is inside a function that returns socket
int sock = socket(nmspace,style,protocol);
int ret;
struct hostent *hinfo;
if(sock<0){
printf("Error occurred while creating socket:%d\n",sock);
printf("%s\n",strerror(errno));
return -1;
}
memset(&dest, 0, sizeof(struct sockaddr_in));
hinfo = gethostbyname(rmserver);
if(hinfo == NULL)
printf("getbyname failed!\n");
dest.sin_family = AF_INET;
dest.sin_addr = *(struct in_addr *)(hinfo->h_addr);
dest.sin_port = htons(port);
ret = connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr));
if(ret<0){
printf("Error occurred while connecting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
close(sock);
return -1;
}
server
making the server socket...all this is inside a function that returns the socket>>>>>>
struct sockaddr_in serv;
int mysocket,r;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv, 0, sizeof(struct sockaddr_in));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = INADDR_ANY;
serv.sin_port = htons(port);
r = bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
if(r<0) {
printf("Error occurred binding the socket:%d to the server port:%d\n",mysocket,port);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
r = listen(mysocket, 5);
if(r<0) {
printf("Error occurred while enabling listen on the socket:%d\n",mysocket);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
server accept call>>>>>>
struct sockaddr_in dest;
int socksize=sizeof(struct sockaddr_in);
int consocket;
consocket = accept(sock, (struct sockaddr *)&dest, (socklen_t *)&socksize);
if(consocket<0) {
printf("Error occurred while accepting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
}
Not using select. I hope we don't need that as the sockets are by default blocking.
cheers...raman
Your client should be using connect (man page) rather than accept. Servers use accept to accept incoming connections and to get a new socket unique to that connection, leaving the original file descriptor free for listening and accepting new connections. Clients just use the same socket after the connection is made.
Also, I recommend taking a look at how to use select (man page).