i've made in my windows desktop, a c socket code, but when i compile, it gives me erros, i dnt know how to proceed, can someone help me? i am working in windows 7, but also tried this same code in windows 10, but i got the same errors, here is the c code, i also tried in c++ but got the same errors, c code below:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string.h>
#pragma comment (lib, "Ws2_32.lib")
#define PORT 5555
#define HOST "192.168.1.30"
#define MAX_L 4096
int main(void){
char bfs[MAX_L], bfr[MAX_L];
int sockfd;
socklen_t sin_size = sizeof(struct sockaddr_in);
struct sockaddr_in target_addr;
struct WSAData wsa;
WSAStartup(MAKEWORD(2,2),&wsa);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
target_addr.sin_port = htons(PORT);
target_addr.sin_family = AF_INET;
target_addr.sin_addr.s_addr = inet_addr(HOST);
connect(sockfd, (struct sockaddr *)&target_addr, sin_size);
while(1){
gets(bfs);
send(sockfd, &bfs, MAX_L, 0);
recv(sockfd, &bfr, MAX_L, 0);
printf("%s\n", bfr);
}
closesocket((SOCKET) sockfd);
WSACleanup();
}
error:
gcc -o csocketcode csocketcode.c -lwinsock2
When calling send() and recv(), DON'T use the & operator to pass your char[] arrays. Arrays decay into pointers, so pass the arrays as-is. send() expects a const char*, and recv() expects a char*, but you are passing them both a char(*)[4096] instead, which is not what the functions want. Let the arrays decay to char* for you.
There are other problems with your code:
missing #include <windows.h>
sockfd is declared as int when it should be SOCKET instead.
gets() is dangerous. Also, you are (potentially) sending more data than gets() actually returns.
your use of printf() is expecting null-terminated data, but recv() does not guarantee a null terminator.
no error handling at all.
Try this instead:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <string.h>
#pragma comment (lib, "Ws2_32.lib")
#define PORT 5555
#define HOST "192.168.1.30"
#define MAX_L 4096
int main(void) {
char bfs[MAX_L], bfr[MAX_L];
SOCKET sockfd;
struct sockaddr_in target_addr;
struct WSAData wsa;
int err, num_recvd;
size_t str_len;
err = WSAStartup(MAKEWORD(2,2), &wsa);
if (err != 0) {
fprintf(stderr, "WSAStartup() failed, error %d\n", err);
return -1;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == INVALID_SOCKET) {
err = WSAGetLastError();
fprintf(stderr, "socket() failed, error %d\n", err);
WSACleanup();
return -1;
}
target_addr.sin_port = htons(PORT);
target_addr.sin_family = AF_INET;
target_addr.sin_addr.s_addr = inet_addr(HOST);
if (connect(sockfd, (struct sockaddr *)&target_addr, sizeof(target_addr)) == SOCKET_ERROR) {
err = WSAGetLastError();
fprintf(stderr, "connect() failed, error %d\n", err);
closesocket(sockfd);
WSACleanup();
return -1;
}
while (fgets(bfs, MAX_L, stdin)) {
str_len = strlen(bfs);
if ((str_len > 0) && (bfs[str_len-1] == '\n')) {
--str_len;
}
if (send(sockfd, bfs, str_len, 0) == SOCKET_ERROR) {
err = WSAGetLastError();
fprintf(stderr, "send() failed, error %d\n", err);
closesocket(sockfd);
WSACleanup();
return -1;
}
num_recvd = recv(sockfd, bfr, MAX_L, 0);
if (num_recvd == SOCKET_ERROR) {
err = WSAGetLastError();
fprintf(stderr, "recv() failed, error %d\n", err);
closesocket(sockfd);
WSACleanup();
return -1;
}
if (num_recvd == 0) {
break;
}
printf("%.*s\n", num_recvd, bfr);
}
closesocket(sockfd);
WSACleanup();
return 0;
}
Your code under gcc compiles but cannot be linked because gcc doesn't recognize
#pragma comment (lib, "Ws2_32.lib")
Add -Werror=unknown-pragmas as compiler flag and you will see error: ignoring pragma comment as compiler message.
So you need to pass Ws2_32 library to link in command line:
gcc -o csocketcode csocketcode.c -lWs2_32
gcc tells you about incompatible pointers type (it is treated as warnings), what is described in Chipster's answer. Fix it.
Related
i have written a small c-program for an IPv6 server with winsock2.h When I run the program in Visual Studio, I get the following message all the time: recvfrom failed
I just can't find the error in the recvfrom function. Maybe someone can see why my program does not work at this point, thanks! :-)
Best regards,
Ken
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
socklen_t client_len;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
if (WSAStartup(version, &data) == SOCKET_ERROR) {
printf("WSASStartup failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (server_socket == -1) {
printf("creating socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("creating socket successful\n");
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (const struct sockaddr*) & server_addr,
sizeof(server_addr)) == -1) {
printf("bind socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("bind socket successful\n");
}
while (1) {
memset(&client_addr, 0, sizeof(client_addr));
memset(buf, 0, sizeof(buf));
if (recvfrom(server_socket, (char*)buf, 1024, 0,
(struct sockaddr*) & client_addr,
sizeof(client_addr)) == -1) {
printf("recvfrom failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("recvfrom successful");
}
printf("%s\n", buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr,
clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
You are misusing recvfrom(). The fromlen parameter expects to receive an int* pointer that points to an int, which on input specifies the byte size of the sockaddr buffer being passed in the from parameter, and on output receives the byte size of the sockaddr written to the from buffer.
There are also some other minor bugs in your code:
WSAStartup() does not return SOCKET_ERROR on failure, it returns an actual error code.
you are ignoring the return value of recvfrom(), which tells you how many bytes were actually written to your buf. You are assuming buf is always null-terminated when passing it to printf("%s"), but that is not guaranteed. You are zeroing out buf to initialize it with null terminators, which is fine if recvfrom() receives a datagram containing less than 1024 bytes. But if it receives a datagram with exactly 1024 bytes than all of your null terminators will be overwritten and there will be no terminator left for printf() to find (if recvfrom() receives a datagram with more than 1024 bytes, it will fail with a WSAEMSGSIZE error, which is not a fatal error but you are treating it as if it were). Rather than rely on any null terminators at all, you can pass the return value of recvfrom() to printf() for the buffer size. No need to waste overhead zeroing out what recvfrom() will overwrite.
Try this instead:
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
int client_len, num_recvd;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
int errCode = WSAStartup(version, &data);
if (errCode != 0) {
printf("WSAStartup failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
server_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (server_socket == INVALID_SOCKET) {
errCode = WSAGetLastError();
printf("creating socket failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successful\n");
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (struct sockaddr*) &server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
errCode = WSAGetLastError();
printf("bind socket failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successful\n");
while (1) {
client_len = sizeof(client_addr);
num_recvd = recvfrom(server_socket, buf, sizeof(buf), 0, (struct sockaddr*) &client_addr, &client_len);
if (num_recvd == SOCKET_ERROR) {
errCode = WSAGetLastError();
if (errCode != WSAEMSGSIZE) {
printf("recvfrom failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("recvfrom truncated a datagram larger than %u bytes!\n", sizeof(buf));
num_recvd = sizeof(buf);
}
else {
printf("recvfrom successful\n");
}
printf("%.*s\n", num_recvd, buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
I have a very simple client-server code. Every time a server receives a packet I create a thread that handles it. The code is shown below. What I can't understand is that after sometime my server stops receiving any data. It just listens and doesn't receive anything. I can't figure out why. Does anyone know the reason.
I'm building my code on Lenovo T470s Fedora 29, Linux user 4.19.15-300.fc29.x86_64 #1 SMP Mon Jan 14 16:32:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Any help is appreciated.
/*
server.c
cc -std=gnu11 -pedantic -lpthread server.c -o server.c
*/
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE_B 1024
static int fd;
static void *handlePacketThreadWrapper(void *arg);
int main(void)
{
pthread_t t;
struct pollfd pollfd;
struct sockaddr_in addr;
uint16_t port = 9500;
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0)
{
printf("errno: %d. %s. Failed to create a socket",
errno, strerror(errno));
exit(EXIT_FAILURE);
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
while(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("errno: %d. %s. Failed to bind socket. Will attempt again.", errno,
strerror(errno));
sleep(1);
}
memset(&addr, 0, sizeof(addr));
pollfd.fd = fd;
pollfd.events = POLLIN;
while(true)
{
if (poll(&pollfd, 1, -1) < 0)
{
printf("errno: %d. %s", errno, strerror(errno));
}
else
{
pthread_create(&t, NULL, handlePacketThreadWrapper, NULL);
}
}
return 0;
}
static void *handlePacketThreadWrapper(void *arg)
{
uint8_t buf[BUF_SIZE_B];
size_t strLen, fullIPLen;
ssize_t
i,
n
;
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr);
char *str, *fullIP;
n = recvfrom(fd, buf, sizeof(buf), 0,
(struct sockaddr *)&addr, (socklen_t *)&addrLen);
if (n < 0)
{
printf("errno: %d. %s. Failed to create a socket",
errno, strerror(errno));
}
else
{
for (i = 0; i < n; i++)
{
printf("0x%02X ", buf[i]);
}
printf("\n");
}
return NULL;
}
And here is my client code:
/*
client.c
cc -std=gnu11 -pedantic client.c -o client.c
*/
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#define BUF_SIZE_B 1024
int main(void)
{
ssize_t size, i;
struct sockaddr_in dest;
int fd;
char *toIP = "127.0.0.1";
uint16_t toPort = 9500;
uint8_t buf[BUF_SIZE_B];
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0)
{
printf("errno: %d, %s", errno, strerror(errno));
exit(EXIT_FAILURE);
}
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(toIP);
dest.sin_port = htons(toPort);
while(true)
{
size = sendto(fd, buf, sizeof(buf), 0, (struct sockaddr*)&dest, sizeof(dest));
if (size < 0)
{
printf("errno: %d. %s. Failed to send bytes to %s:%hu.",
errno, strerror(errno), toIP, toPort);
}
else
{
for (i = 0; i < size; i++)
printf("0x%02X ", buf[i]);
printf("\n");
}
usleep(1000);
}
return 0;
}
You can only have as many threads running simultaneously, as ulimit -u reports.
Your server never joins the threads, and once the limit is reached it starts failing to create them.
In your server the main thread and the created thread(s) access the same socket (fd) without any protection like exclusive section, so the execution of poll and recvfrom can be done in any order including simultaneously, that probably destruct the internal data of the socket.
You can do for example :
while(true)
{
if (poll(&pollfd, 1, -1) < 0)
{
printf("errno: %d. %s", errno, strerror(errno));
}
else
{
pthread_create(&t, NULL, handlePacketThreadWrapper, NULL);
pthread_join(&t);
}
}
That both protect the use of the socket and avoid zombie thread as mentioned by user58697 in an other answer (the threads are not detached by default).
Of course doing that limit the interest to read on the socket in an other thread, but your code is not really compatible with multi threading for several reasons
I've been a Unix programmer for a decent amount of time, and I know pretty well the system's socket API, I use it mostly for networking.
The thing is that I'm currently trying to create a cross-platform software, and so I began to learn how to compile my source code into windows executable files.
I've created a startup() function which does the simplest thing: connect to a server (of which IP is given), and return -1 on failure. On Linux my code runs smooth, but on Windows(7) I get the same error on some machines - "Connect()" function failed, errno: "Result too large" which (by what I understood) means it could no find any listening server on that IP, but on others it runs well.
Here is the code (win version):
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
int startup(struct sockaddr_in sin)
{
int sockfd, soaddr;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
fprintf(stderr, "socket:%s\n", strerror(errno));
return(-1);
}
soaddr = sizeof(sin);
if(connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", strerror(errno));
return(-1);
}
return sockfd;
}
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
sockfd = startup(sin);
// Code continues
return(0);
}
note:ADDR has been changed for privacy reasons, but there is a working server on that machine
So, why exactly am I getting this error ?
WinSock does not use errno, it uses WSAGetLastError() instead.
WinSock does not use file descriptors for sockets, it uses actual kernel objects. On Windows, you need to use the SOCKET handle type, not int, for your socket variables (or at least type-cast SOCKET values to (u)intptr_t and then type-cast back to SOCKET when calling WinSock functions).
You can use the Win32 API FormatMessage() function to get a human readable string for a WinSock error code.
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
__declspec(thread) char errmsg[256];
char* sockerr(int errcode)
{
DWORD len = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, 0, errmsg, 255, NULL);
if (len != 0)
errmsg[len] = 0;
else
sprintf(errmsg, "error %d", errcode);
return errmsg;
}
int startup()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(1,1), &wsaData);
if (ret != 0) {
fprintf(stderr, "WSAStartup:%s\n", sockerr(ret));
return(ret);
}
return(0);
}
void cleanup()
{
WSACleanup();
}
SOCKET connectToServer(struct sockaddr_in sin)
{
SOCKET sockfd;
int soaddr;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == INVALID_SOCKET)
{
fprintf(stderr, "socket:%s\n", sockerr(WSAGetLastError()));
return(INVALID_SOCKET);
}
soaddr = sizeof(sin);
if (connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", sockerr(WSAGetLastError()));
closesocket(sockfd);
return(INVALID_SOCKET);
}
return(sockfd);
}
int main(int argc, char *argv[])
{
SOCKET sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
if (startup() != 0) {
exit(1);
}
sockfd = connectToServer(sin);
if (sockfd != INVALID_SOCKET)
{
// ...
closesocket(sockfd);
}
cleanup();
return(0);
}
You will have to take these differences into consideration when writing cross-platform socket code.
According to your code you are running client socket in windows machine.You need to load runtime libraries for windows as
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
You can refer to Windows Client Socket Source. Hope this works for you.
This is a basic TCP-Server implementation for teaching purposes. Are there any error or improvements to do. Any suggest is welcome!
I only have a doubt:
signal(SIGCHLD, SIG_IGN);
Is that call used to prevent zoombie-child processes?
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BACKLOG 5
#define MAXSIZE 1024 //max-bytes for read-buffer
void main(){
int sock_ds, ret, length;
int acc_ds; //Accept socket descriptor
struct sockaddr_in addr; //this addres
struct sockaddr rem_addr; //remote address (generic)
char buff[MAXSIZE];
sock_ds = socket(AF_INET, SOCK_STREAM, 0); // => TCP
bzero((char *)&addr, sizeof(addr)); //reset struct
addr.sin_family = AF_INET;
addr.sin_port = htons(25000);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock_ds, &addr, sizeof(addr));
if(ret == -1){
perror("Binding error");
exit(1);
}
ret = listen(sock_ds, BACKLOG); // backlog queue
if(ret == -1){
perror("Listen error");
exit(1);
}
length = sizeof(rem_addr);
signal(SIGCHLD, SIG_IGN); //zombie children management
/*Busy-waiting (server) and concurrency */
while(1){
/*Repeat until success*/
while(acc_ds = accept(sock_ds, &rem_addr, &length) == -1){
if(fork() == 0){ //child-process
close(sock_ds); //unused from child
do{
read(acc_ds, buff, MAXSIZE);
printf("Message from remote host:&s\n", buff);
}while(strcmp(buff, "quit") == 0);
/*Transimission completed: server response */
write(acc_ds, "Reading Done", 10);
close(acc_ds); //socket closed
exit(0); //exiting from child
}
else{
close(acc_ds); //unused from parent
}
}
}
}
Return type of main is not int. It should be. Either return EXIT_SUCCESS or EXIT_FAILURE.
Result of socket() call is not checked. It should be, or bind will fail but perror() will tell "Invalid argument" instead of the actual error.
A return value of read() is not checked possibly triggering undefined behavior when printing.
There is no &s format specified, it should be %s.
%s expects a null-terminated string. This is not guaranteed by the code (see point #3). strcmp() may crap out as well.
As for the SIGCHLD, #cnicutar has kindly answered that already, nothing to add there.
Hope it helps. Good Luck!
Yes, that's exactly what ignoring SIGCHLD is for. From TLPI:
There is a further possibility for dealing with dead child processes.
Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any
child process that subsequently terminates to be immediately removed
from the system instead of being converted into a zombie.
It is standard across Unix implementations.
I need to learn how this works, too. So, I googled "simple tcp-server", found this little program, and fixed up the code to be happier with gcc -Wall and the comments. here is what I put together:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#define BACKLOG 5
#define MAXSIZE 1024 //max-bytes for read-buffer
#define PORT 25000
/****************************************************************/
int main() {
int sock_ds, ret; unsigned int length;
int acc_ds; //Accept socket descriptor
struct sockaddr_in addr; //this address
struct sockaddr rem_addr; //remote address (generic)
char buff[MAXSIZE+1];
if (!(sock_ds = socket(AF_INET, SOCK_STREAM, 0))) perror("socket call failed"); // => TCP
bzero( (char *)&addr, sizeof(addr)); //reset struct
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sock_ds, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
perror("Binding error");
exit(EXIT_FAILURE);
}
ret = listen(sock_ds, BACKLOG); // backlog queue
if (ret == (-1)) {
perror("Listen error");
exit(EXIT_FAILURE);
}
length = sizeof (rem_addr);
// sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management
/*Busy-waiting (server) and concurrency */
while (1) {
fprintf(stderr, "[Waiting for client %d]\n", getpid());
/*Repeat until success*/
while ((acc_ds = accept(sock_ds, &rem_addr, &length)) == -1) {
fprintf(stderr, "[Accepted from client %d]\n", getpid());
if (fork() == 0) { //child-process
close(sock_ds); //unused from child
fprintf(stderr, "[Reading from client %d]\n", getpid());
while (read(acc_ds, buff, MAXSIZE)) {
buff[MAXSIZE]='\0';
printf("Message from remote host:%s\n", buff);
fflush(stdout);
if (strncmp (buff, "quit", 5) == 0) break;
}
/*Transmission completed: server response */
if (write(acc_ds, "Reading Done", 10)) fprintf(stderr, "failed write\n");
close(acc_ds); //socket closed
exit(EXIT_SUCCESS); //exiting from child
}
else{
close(acc_ds); //unused from parent
}
}
}
return EXIT_SUCCESS;
}
two problems. the first is that gnu linux gcc refuses to accept
sigaction(SIGCHLD, SA_NOCLDWAIT); //zombie children management
tcp-server2.c: In function ‘main’:
tcp-server2.c:53:3: warning: passing argument 2 of ‘sigaction’ makes pointer from integer without a cast [enabled by default]
In file included from tcp-server2.c:7:0:
/usr/include/signal.h:267:12: note: expected ‘const struct sigaction * restrict’ but argument is of type ‘int’
tcp-server2.c:53:3: error: too few arguments to function ‘sigaction’
In file included from tcp-server2.c:7:0:
/usr/include/signal.h:267:12: note: declared here
the second is that when I telnet to port 25000 and type a few things, nothing ever is echoed as received. so the server does not seem to work. it never gets to accepted from client.
now, I could pick up a programming example from somewhere else, but I thought I should just report this here, so we get a simplest tcp server posted correct here.
I have a C function to check a host and its port, when I use FQDN host name, the function return error like: connect() failed: connect time out, but if I use IP address instead, it seems ok, how to fix this?
Thanks.
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock;
struct sockaddr_in chksock;
struct hostent *host = NULL;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
syslog(LOG_ERR, "socket() creation error: %s", strerror(errno));
return 0;
}
memset(&chksock, 0, sizeof(chksock));
chksock.sin_family = AF_INET;
chksock.sin_port = htons(chkport);
/* get the server address */
if (inet_pton(AF_INET, chkhost, &(chksock.sin_addr.s_addr)) <= 0) {
if ((host = gethostbyname(chkhost)) == NULL) {
syslog(LOG_ERR, "%s", hstrerror(h_errno));
return 0;
}
memcpy(&(chksock.sin_addr.s_addr), &(host->h_addr_list[0]),
sizeof(struct in_addr));
}
/* try to connect */
if (connect(sock, (struct sockaddr *) &chksock, sizeof(chksock)) < 0) {
syslog(LOG_ERR, "connect() failed: %s", strerror(errno));
return 0;
}
close(sock);
return 1;
}
inet_pton() is the wrong task for that. It only accepts numerical addresses.
In former times, people used to use gethostbyname() for name resolution.
But as we have 2012 meanwhile, this method is outdated for several years now, as it is still restricted to AF_INET.
With the program below, you should achieve about the same and stay future compatible.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock = -1;
struct addrinfo * res, *rp;
int ret = 0;
char sport[10];
snprintf(sport, sizeof sport, "%d", chkport);
struct addrinfo hints = { .ai_socktype=SOCK_STREAM };
if (getaddrinfo(chkhost, sport, &hints, &res)) {
perror("gai");
return 0;
}
for (rp = res; rp && !ret; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
char node[200], service[100];
getnameinfo(res->ai_addr, res->ai_addrlen, node, sizeof node, service, sizeof
service, NI_NUMERICHOST);
printf("Success on %s, %s\n", node, service);
ret = 1; /* Success */
}
close(sock);
}
freeaddrinfo(res);
return ret;
}
int main(int argc, char** argv) {
if (argc > 1) {
printf("%s: %d\n", argv[1], is_network_up(argv[1], 22));
}
}
Make sure name resolution is working. See if you can ping the machine by name from the exact same environment in which your code runs.
If ping works, try telnet <machinename> <portnumber> -- If both of those work it is likely a problem with your code (which I did not look at in depth, too sleepy:).
Make sure you're converting anything returned by the OS as an ip address from network order to host order. IIRC, gethostbyname returns binary ip addresses in network order.
ntohl can be used on chksock.sin_addr.s_addr after the memcpy to achieve this.