I've successfully made an "echo client", and I'd like to add robustness before moving along to the rest of my project. Notably I'd like to view the "TCP window size" value inside the TCP header, and ensure that I don't flood the server with my next transmission.
I am not sure if this is possible without using raw sockets and forming/parsing the TCP header myself. While that isn't impossible, I'd prefer to use built in functions to access the header with my current code if possible. Please let me know if you have any suggestions.
#include "../include/a8gcc.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#define buffer_len 512
/* server address */
#define SERVER "192.168.2.115"
/* server port number */
#define SERVPORT 10001
int main(void)
{
struct sockaddr_in serv_addr;
struct hostent *server;
int sock_fd, num_read = 0;
char in_data[buffer_len];
printf("is_ethernet from GCC");
setbuf(stdout, NULL);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd < 0){
perror("Opening socket error");
exit(1);
}else{
printf("Opening the socket...OK.\n");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
server = gethostbyname(SERVER);
if(server == NULL){
printf("%s \n", h_errno);
perror("getting host address error");
exit(1);
}
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(SERVPORT);
if (connect(sock_fd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
perror("ERROR connecting");
exit(1);
}
while(1){
num_read = read(sock_fd,in_data,buffer_len);
write(sock_fd,in_data,num_read);
}
return 0;
}
I do not believe that it is possible for you to examine the actual content of the TCP/IP headers from within your code unless you are going to use raw sockets and generate the packets yourself. :( Sorry!
Related
I'm trying to get into socket programming with C and my problem is that no matter what I try I cannot get my client-server model to connect over the internet except through logging into my router and port forwarding the port I'm inputting in my program. Basically my server.c blocks and waits for a connection, then it sends the time of the server to the client once it connects. I've tried to open ports on both my machines like this:
sudo iptables -A INPUT -p tcp --dport 20001 -j ACCEPT
and I downloaded the iptables-persistent package that makes sure the rules stay on a reboot. iptables -L shows me that the ports are open on both machines, but the connection still times out. I know that somehow this is possible because Steam and Discord don't have to port forward anything and they still make it happen. I have a server at home so if the solution requires a 'middle man' server to facilitate a connection between two clients, then it won't be a problem for me. Also I am on two separate networks, so that's not the problem.
The server.c:
/* --- server.c --- */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
/* creates an UN-named socket inside the kernel and returns
* an integer known as socket descriptor
* This function takes domain/family as its first argument.
* For Internet family of IPv4 addresses we use AF_INET
*/
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(20001);
/* The call to the function "bind()" assigns the details specified
* in the structure 『serv_addr' to the socket created in the step above
*/
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
/* The call to the function "listen()" with second argument as 10 specifies
* maximum number of client connections that server will queue for this listening
* socket.
*/
listen(listenfd, 10);
while(1)
{
/* In the call to accept(), the server is put to sleep and when for an incoming
* client request, the three way TCP handshake* is complete, the function accept()
* wakes up and returns the socket descriptor representing the client socket.
*/
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
/* As soon as server gets a request from client, it prepares the date and time and
* writes on the client socket through the descriptor returned by accept()
*/
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
and client.c:
/* --- client.c --- */
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
/* a socket is created through call to socket() function */
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(20001);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
/* Information like IP address of the remote host and its port is
* bundled up in a structure and a call to function connect() is made
* which tries to connect this socket with the socket (IP address and port)
* of the remote host
*/
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
/* Once the sockets are connected, the server sends the data (date+time)
* on clients socket through clients socket descriptor and client can read it
* through normal read call on the its socket descriptor.
*/
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
This line is saying what port you're connecting to on the server
serv_addr.sin_port = htons(42020);
change it to the same port number as the server and it should work just fine.
serv_addr.sin_port = htons(20001);
#include <stdio.h>
#include "http.h"
#define MAX 4096
int main()
{
char s_msg[MAX], c_msg[MAX];
printf("%d", strlen(s_msg));
// Clean buffers:
memset(s_msg,'\0',sizeof(s_msg));
memset(c_msg,'\0',sizeof(c_msg));
char *msg = "GET / HTTP/1.1\r\nUser-Agent: Hellothere\r\nHost: HOSTNAME\r\n\r\n";
int soc = init_client();
int con = connection("HOSTNAME",80);
if(send(socket_desc, msg, strlen(msg), 0) < 0){
printf("Unable to send message\n");
return -1;
}
if (recv(socket_desc, c_msg , MAX, 0)<0)
{
printf("Failed to read from server\n");
return -1;
}
printf("Recieved from server : %s\n",c_msg);
return 0;
}
Using ngrok you need to use Host header
I want to write a LINUX C application that can monitor the system TCP listening ports which provide web service. Whenever a new port is listened, or one port is released, I can detect it in real time.
Does Linux provide system call to provide this feature? Or Should I hook the Kernel function?
The code below will help you check if a port is open, if you need real time processing; you may continuously run the program in a separate thread.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
int portno = 22;
char *hostname = "localhost;
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
server = gethostbyname(hostname);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
printf("Port is closed");
} else {
printf("Port is active");
}
close(sockfd);
return 0;
}
My code will always proc the "Binding Failure" error and I do not know why. I have read the man page multiple times and I can't find anything wrong with the code, can someone please steer me in the right direction?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
#define BACKLOG 10
int main()
{
struct sockaddr_in server;
struct sockaddr_in dest;
int status,socket_fd, client_fd,num;
socklen_t size;
char buffer[10241];
char *buff;
// memset(buffer,0,sizeof(buffer));
int yes =1;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
fprintf(stderr, "Socket failure!!\n");
exit(1);
}
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
memset(&server, 0, sizeof(server));
memset(&dest,0,sizeof(dest));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1) { //sizeof(struct sockaddr)
fprintf(stderr, "Binding Failure\n");
exit(1);
//other irrelevant code starts here
If netstat -an|grep 3490 really shows 127.0.0.1 you have another process listening at the port, bound to 127.0.0.1 instead of INADDR_ANY, which is why the SO_REUSEADDR didn't work. But you will never know for sure until you take my advice above.
After using perror, I found that the address was taken and I switched to another port and it worked!
I am performing communication between client(windows) and server(linux RT) in c. I have written a client code for windows operating system (one laptop) and server code for linux operating system (another laptop). I am connecting the both laptop via ethernet cable and configured them on the same subnet.
SERVER.c : Linux
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
else
printf("Server : Socket() successful\n");
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
err("bind");
else
printf("Server : bind() successful\n");
while(1)
{
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr,
&slen)==-1)
err("recvfrom()");
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
}
close(sockfd);
return 0;
}
CLIENT.c - windows
#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <winsock.h>
#include <io.h>
#define BUFLEN 512
#define PORT 9930
void err(char *str)
{
perror(str);
exit(1);
}
int main(void)
{
struct sockaddr_in my_addr, cli_addr;
int sockfd, i;
socklen_t slen=sizeof(cli_addr);
char buf[BUFLEN];
WORD wVersionRequested;
WSADATA wsaData;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
if (WSAStartup (wVersionRequested, &wsaData) != 0){
printf("Winsock initialised failed \n");
} else {
printf("Initialised\n");
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(argv[1], &serv_addr.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
while(1)
{
printf("\nEnter data to send(Type exit and press enter to exit) : ");
scanf("%[^\n]",buf);
getchar();
if(strcmp(buf,"exit") == 0)
exit(0);
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
err("sendto()");
}
close(sockfd);
return 0;
}
My question :
Is it possible to perform communication like this ??
Do I want to take specific measures for doing this ??
Please give ideas regarding this ?
You can connect two systems directly (via ethernet cable), but typically you must use a special cable for that: it is called a "crossover cable". Otherwise no connection is possible.
Newer network controllers implement a detection for this kind of setup, so it might be possible to use a standard cable for this setup, but this depends on the network controllers build into the two systems. You will have to try or consult the documentation.
Also it migh be that you have to select some special configuration on the MS-Windows side (inside the network adapter configuration) for this to work. I experienced communication problems with the standard setup a few times. You can consult google for those settings.
I am reading a book on sockets in c and am making a very simple server program. I copied the code verbatim. There is nothing trying to connect to this server program yet and have change the port multiple times to make sure.
The program is failing on the accept method on the first run of the loop. From what I read in the man pages, accept is supposed to block the caller until a connection is made, and not fail if there aren't connections in the queue like it is doing. Is there any reason accept would be returning a value less than 0? I will post the code up to where it fails:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//Max number of outstanding connection requests
#define MAXPEDNING 5
#define NONE
#define BUFSIZE 1024
int main(int argc, char **argv)
{
in_port_t servPort;
#ifdef CMDLINE
if(argc != 2)
{
puts("Error! Usage is <Server Port>");
return 0;
}
servPort = atoi(argv+1);
#endif //CMDLINE
#ifdef NONE
servPort = 2549;
#endif //NONE
int servSock;
if((servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
puts("socket() failed");
return 0;
}
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
printf("Port in network order: %d\nPort in host order:%d\n", servAddr.sin_port, ntohs(servAddr.sin_port));
if((bind(servSock, (struct sockaddr*) &servAddr, sizeof(servAddr)))<0)
{
puts("bind failed");
return 0;
}
while(1)
{
struct sockaddr_in clntAddr;
socklen_t clntAddrLen = sizeof(clntAddr);
int clntSock = accept(servSock, (struct sockaddr*) &clntAddr, &clntAddrLen);
if(clntSock < 0)
{
puts("accept failed");
return 0;
}
It reaches the accept failed and quits. The only thing that is odd about my setup is that I am on a Debian VM (VirtualBox) and I am wondering if network operations are handled in a weird way. I shouldn't be even trying to accept anything because there are no connections.
You need to call listen() in between bind() and accept().