I'm completely new to C.
And am following this yt tutorial on sockets. However he's using the close(sock) function. There's 2 problems:
There's no variable called sock. The socket is called something else.
I can't find the close function. The compiler is saying that the function doesn't exist
Can you please explain. This question might seem a little too dumb.
Here's the Client code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
// Create a socket
int network_socket;
network_socket = socket(AF_INET, SOCK_STREAM, 0);
// Address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
int connection = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
printf("%d\n", connection);
char response[256];
recv(network_socket, &response, sizeof(response), 0);
printf("%s\n", response);
return 0;
}
There's no variable called sock. The socket is called something else.
Yes, it's network_socket in your code. So you want close(network_socket);.
I can't find the close function. The compiler is saying that the function doesn't exist
You need #include <unistd.h>, which is where close() is declared. (If you look at man close you'll see this at the top.)
You need to pass the socket file descriptor as the argument for close(). Which, for your code, is network_socket. So, close() need to be called as close(network_socket);
Also, you need to use the <unistd.h> header for the close() function.
Related
The following server in C doesn't work as expected. Upon running it the first time, no issues occur. Every next time you run it, it fails to bind. The solution of the question that some of you will probably mark as duplicate doesn't work either, regardless of the fact that setsockopt(...) is successful.
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8080
#define SA struct sockaddr
int main() {
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) puts("Socket creation failed."), exit(0);
else puts("Socket created.");
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, optLen);
servaddr.sin_family = AF_INET, servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (SA *) &servaddr, sizeof(servaddr))) {
puts("Bind failed.");
shutdown(sockfd, 2);
return 12;
}
else puts("Bound.");
if(listen(sockfd, 5)) puts("Listen failed."), exit(2);
else puts("Listening: ");
int len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);
if(connfd < 0) puts("Connection failed."), exit(3);
else puts("Accepted.");
close(connfd);
return 0;
}
Things I've tried so far:
using setsockopt(...) has no effect
shutdown(...) doesn't work either
closesocket(...) is part of the Windows API, which I just have no intention to use
If I decide to ignore the "Address already in use" error, accept(...) fails with Invalid argument
If it matters I'm using CLion with cygwin under Windows 10.
"If it matters I'm using CLion with cygwin under Windows 10."
I strongly suspect that this matters.
When I compile your code exactly as you posted it, it behaves according to your desired / expected behavior.
When I comment out the setsockopt() call, I need to wait until the TIME_WAIT expires before being able to re-bind the same address+port, which is also expected.
I'm using gcc on macOS, so I suspect that your compilation and/or runtime environment has something to do with your code not working as expected for you. One way you could verify this if you don't have access to a physical Linux machine, and if you cannot set up dual-boot on the Windows machine that you do have, would be to spin up a small Linux instance at Digital Ocean, AWS, or some other cloud provider.
EDIT #1
I repeated this on a DO Linux host, and I have confirmed that your original code works as expected.
I'm learning socket programming in C. I have gotten my server to create a socket that was successful, but when I try to bind my socket to a port nothing happens. No error occurs and it is not successful. It's as if the bind() function is not even executing at all.
I've checked out the documentation on the bind() function here but there's no mention of why it won't execute at all. I've also tried searching through this site with no avail.
I also tried following this tutorial from start to finish but the error (or lack thereof) still occurs.
Here is my full code leading up to the problem:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "include.h"
int main() {
// Descriptors. Used to check the status of functions such as socket, listen, bind etc.
// If a descriptor is equal to 0, then everything is okay. Else, if they are equal to -1, something went wrong.
int socketDescriptor, newSocketDescriptor = 1;
// The process ID of a child process (the client) when a new one is spawned (the client connects).
pid_t childPID;
// A string to hold the commands being sent a received.
char* commandBuffer = calloc(BUFFER_SIZE, sizeof(char));
// A structure to hold information on the server address.
struct sockaddr_in serverAddress;
memset(&serverAddress, '\0', sizeof(serverAddress));
// Fill in the server address information.
// Set the address family to AF_INET, which specifies we will be using IPv4.
// htons() takes the given int and converts it to the appropriate format. Used for port numbers.
// inet_addr() takes the given string and converts it to the appropriate format. Used for IP addresses.
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
// A structure to hold information a client when a new one connects to this server.
struct sockaddr_in clientAddress;
memset(&clientAddress, '\0', sizeof(clientAddress));
// socklen_t defines the length of a socket structure. Need this for the accept() function.
socklen_t addressSize;
// Creating the socket.
// AF_NET specifies that we will be using IPv4 addressing.
// SOCK_STREAM specifies that we will be using TCP to communicate.
socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0) {
perror("ERROR CREATING SOCKET");
exit(1);
}
else
printf("Socket created successfully.\n");
// Binding to the specified port. 0 if everything is fine, -1 if there was an error.
if (bind(socketDescriptor, (struct sockaddr*) & serverAddress, sizeof(struct sockaddr_in)) < 0) {
perror("ERROR BINDNING");
exit(1);
}
else
printf("Socket bound to %s:%s.\n", serverAddress.sin_addr.s_addr, serverAddress.sin_port);
The last if statement at the bottom is where the code fails. It should either print and error or print "Socket bound to 127.0.0.1:80" but neither happens. See an example here.
I'm lost for what to do.
A server socket won't show up in a netstat listing unless you call listen after binding the socket.
Also, you're using the %s format specifier in your printf after the bind call on serverAddress.sin_addr.s_addr and serverAddress.sin_port. These are not strings but integers. Using the wrong format specifier invokes undefined behavior and is likely causing your program to crash. Using the correct format specifier such as %d or %x will fix this.
if (bind(socketDescriptor, (struct sockaddr*)&serverAddress, sizeof(struct sockaddr_in)) < 0) {
perror("ERROR BINDNING");
exit(1);
}
else
// use %x to print instead
printf("Socket bound to %x:%x.\n", serverAddress.sin_addr.s_addr, serverAddress.sin_port);
if (listen(socketDescriptor, 3) < 0) {
perror("listen failed");
} else {
printf("socket is listening\n");
}
This question already has answers here:
Why does printf not flush after the call unless a newline is in the format string?
(10 answers)
Closed 4 years ago.
I'm taking a class in the college that require me to create a server-client application, i came up with this code but apparently it has some strange error when I remove the "\n" at the end of the printf(). I already checked with my teacher and it was him who found out that this is was causing my server to freeze and display latter when we send the message, so he put \n in the end of each print(in the beggining there wasn't). We spend a couple of hours trying to find a reason but we didn't find anything to explain, so i'm reaching for you guys(so as my teacher who is curious about), i don't know if we let something pass by.
To create the error that i'm talking about, simply remove \n from each printf and run the code, he'll run but not work properly (even though the port seems to be listen in the telnet command) the lines who was supposed to appear will not show.
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
//criar socket -> bind -> listen -> connection
int socket_name = 0, new_conn = 0;
struct sockaddr_in serv_addr;
char msg_recv[20];
char sendBuff[1025];
socket_name = socket(AF_INET, SOCK_STREAM, 0);
if(socket_name < 0)
{
printf("%s","Failed to create socket, exiting\n");
}else{
printf("%s", "Success\n");
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(socket_name, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(socket_name, 10);
while (1)
{
new_conn = accept(socket_name, (struct sockaddr*)NULL, NULL);
read(new_conn, &msg_recv, sizeof(msg_recv));
printf("New: %s\n", msg_recv);
close(new_conn);
}
return 0;
}
I am testing with nc command, sending a message there, without a client implementation.
I'm pretty sure you guys aren't experiencing any errors, the adding of \n does nothing more than flush your printing buffer and make it, in fact, a visible indication within your stdout or a terminal for this matter.
I am trying to send an array of objects to my C++ client using the code below. I originally was trying to do so with just the http library alone in which i further investigated and found this out to be not correct approach.
What i'm not clear with this is how socket.write("hello C++ client") will allow me to send this string and have it appear in my terminal C++ but using socket.emit("arrayTransfer", arrayOfObjects); or a similar variation of what i'm trying below will not allow me to receive anything, I have tried different variations of sending the array of objects but have not succeeded can someone help me understand what exactly may be going on in this code and how Nodejs handles these types of sockets?
thank you.
Here is my questions I asked before to gain a better understanding perhaps.
NodeJs server and C++ client
var server = require("net").createServer();
var io = require("socket.io")(server);
socket.emit("message", myArray[0].name);
};
io.on("connection", handleClient);
server.listen(8080);
C++ CLIENT CODE BELOW
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define LENGTH (512)
#include <errno.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#define PORT_NUMBER (8080) // port number where to port in application
int clientSocket;
char buffer[LENGTH];
struct sockaddr_in serverAddr;
socklen_t addr_size;
int main()
{
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(PORT_NUMBER);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
recv(clientSocket, buffer, 1024, 0);
printf("This is your message %s", buffer);
close(clientSocket);
return 0;
}
I've been writing some sockets code in C. I need modify packet headers and control how they're sent out, so I took the raw sockets approach. However, the code I wrote will not compile on BSD systems (Mac OS X/Darwin, FreeBSD, etc.)
I've done a bunch of research on this and have found that BSD systems can't handle raw sockets the way Linux (or even Windows) does. From what I've read, it seems I need to use bpf (berkley packet filter), but I can't figure out how bpf works or how I would go about using it with raw sockets.
If someone could shed some light on this one, I'd be very excited :D
P.S. I'll even be happy with some source code showing how raw sockets are handled in a BSD environment. It doesn't have to be a guide or explanation. I just want to see how it works.
Using raw sockets isn't hard but it's not entirely portable. For instance, both in BSD and in Linux you can send whatever you want, but in BSD you can't receive anything that has a handler (like TCP and UDP).
Here is an example program that sends a SYN.
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
int
main(int argc, char *argv[])
{
int s, rc;
struct protoent *p;
struct sockaddr_in sin;
struct tcphdr tcp;
if (argc != 2)
errx(EX_USAGE, "%s addr", argv[0]);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = 0;
/* Parse command line address. */
if (inet_pton(AF_INET, argv[1], &sin.sin_addr) <= 0)
err(EX_USAGE, "Parse address");
/* Look up tcp although it's 6. */
p = getprotobyname("tcp");
if (p == NULL)
err(EX_UNAVAILABLE, "getprotobyname");
/* Make a new shiny (Firefly) socket. */
s = socket(AF_INET, SOCK_RAW, p->p_proto);
if (s < 0)
err(EX_OSERR, "socket");
memset(&tcp, 0, sizeof(tcp));
/* Fill in some random stuff. */
tcp.th_sport = htons(4567);
tcp.th_dport = htons(80);
tcp.th_seq = 4; /* Chosen by fair dice roll. */
tcp.th_ack = 0;
tcp.th_off = 5;
tcp.th_flags = TH_SYN;
tcp.th_win = htonl(65535);
rc = sendto(s, &tcp, sizeof(tcp), 0, (struct sockaddr *)&sin,
sizeof(sin));
printf("Wrote %d bytes\n", rc);
return 0;
}
Of course, more BSD-specific solutions are available. For instance you could use divert(4) to intercept packets as they traverse your system and alter them.