Related
I have read some example and manual about select and accept but I still can't figure out where I did wrong.
I tried to let server communicate with multiple clients. But when I execute server first, then execute client, server will immediately cause segmentation fault( when i == sockfd in server.c). And I tried to print some strings to check which statement cause wrong, it even no print anything after if (i == sockfd). So I really have no idea how to move on, are there any suggestion?
Server.c
char inputBuffer[140] = {};
char message[] = {"Hi,this is server.\n"};
int sockfd = 0,forClientSockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket creation
struct sockaddr_in serverInfo,clientInfo;
socklen_t addrlen = sizeof(clientInfo);
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htons(PORT);
bind(sockfd,(struct sockaddr *)&serverInfo,sizeof(serverInfo));
listen(sockfd,5);
fd_set active_fd_set, read_fd_set;
int i;
struct sockaddr_in clientname;
size_t size;
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sockfd, &active_fd_set);
int fd_max = sockfd;
while (1)
{
/* Block until input arrives on one or more active sockets. */
//FD_ZERO (&active_fd_set);
//FD_SET (sockfd, &active_fd_set);
read_fd_set = active_fd_set;
if (select (fd_max+1, &read_fd_set, NULL, NULL, NULL) < 0)
{
printf("select fail\n");
}
/* Service all the sockets with input pending. */
for (i = 0; i <= fd_max; ++i)
{
//printf("%d\n",i);
if (FD_ISSET (i, &read_fd_set))
{
//printf("inner :%d %d\n",i,sockfd);
if (i == sockfd)
{
/* Connection request on original socket. */
//printf("A");
int new;
size = sizeof (clientname);
new = accept (sockfd,(struct sockaddr *) &clientname,&size);
if (new < 0)
{
printf("accept fail\n");
}
else
{
printf (
"Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
FD_SET (new, &active_fd_set);
if(new > fd_max)
{
fd_max = new;
}
}
}
else
{
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0)
{
close (i);
FD_CLR (i, &active_fd_set);
}
}
}
}
}
return 0;
}
int read_from_client (int filedes)
{
char buffer[140];
int nbytes;
nbytes = recv (filedes, buffer, sizeof(buffer),0);
if (nbytes < 0)
{
/* Read error. */
perror ("read");
exit (EXIT_FAILURE);
}
else if (nbytes == 0)
/* End-of-file. */
return -1;
else
{
/* Data read. */
printf ("Server: got message: `%s'\n", buffer);
return 0;
}
}
client.c
int sockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket connnection
struct sockaddr_in info;
bzero(&info,sizeof(info));
info.sin_family = PF_INET;
//localhost test
info.sin_addr.s_addr = inet_addr(LOCALHOST);
info.sin_port = htons(PORT);
int err;
char *p;
//Send a message to server
err = connect(sockfd,(struct sockaddr *)&info,sizeof(info));
if(err==-1)
printf("Connection error");
while(1)
{
char message[140];
char receiveMessage[140] = {};
fgets(message,140,stdin);
//scanf("%*[^\n]",message);
//printf("%s",message);
/*if(p=strchr(message,'\n')){
*p = 0;
}else{
scanf("%*[^\n]");
scanf("%c");
}
fgets(message,140,stdin);*/
//scanf("%s",message);
send(sockfd,message,sizeof(message),0);
//printf("RCV");
//recv(sockfd,receiveMessage,sizeof(receiveMessage),0);
//printf("%s\n",receiveMessage);
}
thanks !!
I've set up a very simple C socket server, there are two files.
main.c:
#include "socket_server.h"
#include "main.h"
int main (int argc, char* argv[])
{
start_socket_server(SOCKET_SERVER_PORT);
while (1)
{
update_clients();
}
return 0;
}
socket_server.c:
#include "socket_server.h"
int listen_fd, fdmax, newfd, nbytes, i, j, k;
char buf[256];
fd_set master;
fd_set read_fds;
struct timeval tv;
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
void update_clients()
{
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, &tv);
for(i = 0; i<= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
fprintf(stderr, "New connection!");
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
}
}
}
}
Then I have a simple flash file to connect to it with the following actionscript:
var socket = new XMLSocket;
socket.connect("12.34.56.78", 8080);
socket.onConnect = function(status) {
if(status) {
trace("connected");
socket.writeUTF("Hello!");
socket.flush();
} else {
trace("couldn't connect");
}
};
If I run the server, then my actionscript, I would expect the following:
Server sits and waits
Flash file starts
Server says "New connection!" and flash file says "connected"
Server says "Hello!".
Only 1-3 happen. "Hello!" is never output to my terminal. In fact as best I can tell this block:
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
for(j = 0; j <= fdmax; j++)
{
if(FD_ISSET(j, &master))
{
if(j != listen_fd && j != i)
{
fprintf(stderr, "%s", buf);
}
}
}
}
Is never executed at all (except for when I close my flash file and the server prints "Dead".
What's going on? Why can't I see the data sent from flash? I've managed to send data TO flash, but I haven't been able to receive any FROM it. Also this is being run from within flash, so there is no need to worry about policy files at this stage.
You need to set all your sockets to be non-blocking. For example,
void start_socket_server(int port)
{
struct sockaddr_in servaddr;
int val;
FD_ZERO(&master);
FD_ZERO(&read_fds);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(port);
tv.tv_sec = 0;
tv.tv_usec = 100;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == ioctl(listen_fd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
FD_SET(listen_fd, &master);
fdmax = listen_fd;
}
...
if (i == listen_fd) //new connection
{
newfd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
if (newfd != -1)
{
int val;
fprintf(stderr, "New connection!");
if (-1 == ioctl(newfd, FIONBIO, (val = 1, &val)))
{
perror("ioctl failed!\n");
goto ERROR; /* TODO: or however else you want to deal with errors */
}
FD_SET(newfd, &master);
if (newfd > fdmax) {
fdmax = newfd;
}
}
} else {
nbytes = recv(i, buf, sizeof buf, 0);
if(nbytes <= 0)
{
fprintf(stderr, "Dead");
close(i);
FD_CLR(i, &master);
} else {
fprintf(stdout, "Received %d bytes: '%s'\n", nbytes, buf);
}
}
You should also do this on your main listening socket too after you create it initially so that you can't get stuck in a call to accept() somehow.
Also, the way you are outputting read-in data doesn't make much sense. As initially posted, the code would only print out if it had multiple client connections established. Then, when data was read in, it would print it N - 1 times, where N was the number of current client connections.
I need help debugging some code for a multiplayer game with a single server (acting as a master) and multiple clients. I want to connect those multiple clients to the server using the select and FD_Set functions.
Once the client connects to the server, I save their file descriptor in an array and check if data is available on file to read (using select). If yes, read the data, else I want to broadcast a message to all clients. This is run repeatedly in a loop. Every second, I want to broadcast a message to all clients. At the same time, I want to receive data from client too. So I am checking the availabity of data with the help of select function.
Here is my code:
Server.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include "sys/select.h"
#include <fcntl.h>
#define PORT 5000
#define BUF_SIZE 2000
#define CLADDR_LEN 100
int arr[4] = { 0 };
char clientAddr[4][CLADDR_LEN];
void main() {
struct sockaddr_in addr, cl_addr;
int sockfd, len, ret, newsockfd;
char buffer[BUF_SIZE];
fd_set fds;
int maxfd = -1;
int i = 0, j = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = PORT;
ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error binding!\n");
exit(1);
}
printf("Binding done...\n");
printf("Waiting for a connection...\n");
listen(sockfd, 4);
for (j = 0; j < 2; j++) { //infinite loop
len = sizeof(cl_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cl_addr, &len);
if (newsockfd < 0) {
printf("Error accepting connection!\n");
exit(1);
}
printf("Connection accepted...\n");
inet_ntop(AF_INET, &(cl_addr.sin_addr), clientAddr[j], CLADDR_LEN);
arr[j] = newsockfd;
printf("\n%d", newsockfd);
//FD_ZERO(&fds);
//FD_SET(newsockfd, &fds);
}
close(sockfd);
for (j = 0; j < 2; j++) {
if (arr[j] > maxfd)
maxfd = arr[j];
// FD_SET(arr[j], &fds);
// fcntl(arr[i], F_SETFL, O_NONBLOCK); //stop listening for new connections by the main process.
} //the child will continue to listen.
//the main process now handles the connected client.
while (1) {
for (i = 0; i < 2; i++) {
FD_SET(arr[i], &fds);
}
int returned = select(maxfd + 1, &fds, NULL, NULL, NULL);
if (returned) {
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("%s", buffer);
}
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
}
/*while (1) {
for (j = 0; j < 2; j++) {
memset(buffer, 0, BUF_SIZE);
if (FD_ISSET(arr[j], &fds)) {
ret = recvfrom(arr[j], buffer, BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, &len);
if (ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
printf("Received data from %s: %s\n", clientAddr[j], buffer);
}
}
for (j = 0; j < 2; j++) {
ret = sendto(arr[j], "abc", BUF_SIZE, 0,
(struct sockaddr *) &cl_addr, len);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
printf("Sent data to %s: %s\n", clientAddr[j], buffer);
}
/* close(arr[0]);
close[arr[1]);
close(arr[2]);
close(arr[3]);
}*/
}
client.c:
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include"netdb.h"
#define PORT 5555
#define BUF_SIZE 2000
int main(int argc, char**argv) {
struct sockaddr_in addr, cl_addr;
int sockfd, ret;
char buffer[BUF_SIZE];
struct hostent * server;
char * serverAddr;
if (argc < 2) {
printf("usage: client < ip address >\n");
exit(1);
}
serverAddr = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serverAddr);
addr.sin_port = PORT;
ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error connecting to the server!\n");
exit(1);
}
printf("Connected to the server...\n");
memset(buffer, 0, BUF_SIZE);
//printf("Enter your message(s): ");
//while (fgets(buffer, BUF_SIZE, stdin) != NULL) {
sleep(10);
ret = sendto(sockfd, "a", BUF_SIZE, 0, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error sending data!\n\t-%s", buffer);
}
ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
if (ret < 0) {
printf("Error receiving data!\n");
} else {
printf("Received: ");
fputs(buffer, stdout);
printf("\n");
}
return 0;
}
(The client is passed an IP address.)
This does not work. While debugging the server, it waits at select and nothing is received or sent. What might the problem be?
Probably because you aren't listening on the right port. The sockaddr_in members needs to be configured in network byte order:
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
above is example how select works, in a while loop you must set timeval structure and socket sd
while (1) {
FD_ZERO(&readfds);
FD_SET(sd, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = select(sd + 1, &readfds, NULL, NULL, &tv);
if (rv == 1) {
/*recvfrom*/
}
}
In security firstly FD_ZERO(&readfds)
and you not have to FDSET your clientfds every while loop. You can set one time before the while.
Id u check the client side and clients send data succesfully check the this line
for (i = 0; i < 2; i++) {
if (FD_ISSET(arr[2], &fds)) {
ret = recvfrom(arr[i], (void*) &buffer, sizeof(buffer), 0,
NULL, NULL);
In your code FD_ISSET(arr[2], &fds) you can change the like this
FD_ISSET(arr[i], &fds) because your for loop do nothing here if you can not change the arr[i]
learning the socket programming in c
use gdb tcpserv , select function always return 1 , i don`t kown why.
not good at english, so i paste the code here. anyone help?
file: sockheader.h
content :
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
#define SERV_PORT 11211
#define SA struct sockaddr
#define LISTENQ 5
#define MAXLINE 1024
typedef void Sigfun(int);
int Socket(int family, int type, int protocol);
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
int Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen);
int Close(int sockfd);
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen);
void Writen(int sockfd, char *writeline, int len);
int str_echo(int sockfd);
int str_echo2sum(int sockfd);
int str_cli(int sockfd);
void sig_chld(int signo);
file: sockheader.c
content:
#include "sockheader.h"
int Socket(int family, int type, int protocol)
{
int fd;
if( (fd = socket(family, type, protocol)) < 0 )
{
perror("socket error!\n");
exit(-1);
}
return fd;
}
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
int bindfd;
if( (bindfd = bind(sockfd, myaddr, addrlen)) < 0 )
{
perror("bind error");
exit(-1);
}
return bindfd;
}
int Listen(int sockfd, int backlog)
{
int res ;
if( (res = listen(sockfd, backlog) ) < 0 )
{
perror("Listen error");
exit(-1);
}
return res;
}
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen)
{
int res ;
if( (res = accept(sockfd, chiaddr, addrlen)) < 0 )
{
perror("accept error");
exit(-1);
}
return res;
}
int Close(int sockfd)
{
close(sockfd);
}
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen)
{
int res ;
if ( (res = connect(sockfd, sa, salen)) < 0)
perror("connect error");
return res;
}
void Writen(int sockfd, char *writeline, int len)
{
write(sockfd, writeline, len);
}
int str_echo(int sockfd)
{
char readline[MAXLINE];
char sendline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
fputs("read str:\n", stdout);
readline[n] = '\0';
strcpy(sendline, "recive str:");
strcat(sendline, readline);
Writen(sockfd, sendline, strlen(sendline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_echo2sum(int sockfd)
{
long arg1, arg2;
char readline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
if( sscanf(readline, "%ld%ld", &arg1, &arg2) == 2 )
{
snprintf(readline, sizeof(readline), "%ld\n", arg1 + arg2);
}
else
{
snprintf(readline, sizeof(readline), "input error\n");
}
n = strlen(readline);
Writen(sockfd, readline, strlen(readline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_cli(int sockfd)
{
char charline[MAXLINE], recvline[MAXLINE];
while(fgets(charline, MAXLINE, stdin) != NULL)
{
fputs("write string\n", stdout);
Writen(sockfd, charline, strlen(charline) + 1);
if(read(sockfd, recvline, MAXLINE) == 0)
{
perror("str_cli:server terminated prematurely");
}
if(fputs(recvline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("cli:out while\n", stdout);
}
int str_cli2(int sockfd)
{
int maxfd1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof = 0;
FD_ZERO(&rset);
for(;;)
{
if(stdineof == 0)
{
FD_SET(fileno(stdin), &rset);
}
FD_SET(sockfd, &rset);
maxfd1 = fileno(stdin) > sockfd ? fileno(stdin) + 1 : sockfd + 1 ;
select(maxfd1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset))
{
if( ( n = read(sockfd, buf, MAXLINE) ) == 0)
{
if(stdineof == 1)
{
return ;
}
else
{
perror("str_cli2:server terminated ");
exit(-1);
}
}
Writen(fileno(stdout), buf, n );
}
if( FD_ISSET(fileno(stdin), &rset) )
{
if( ( n = read(stdin, buf, MAXLINE) ) == 0)
{
stdineof = 1;
shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(stdin), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
printf("child %d terminated\n", pid);
}
return;
}
file:tcpcli05.c
content:
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int sockfd, i;
struct sockaddr_in cliaddr;
for(i = 0; i < 5; i++)
{
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &cliaddr.sin_addr.s_addr);
Connect(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}
str_cli2(sockfd);
return 0;
}
file:tcpserv05.c
content:
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int i, maxi, maxfd, listenfd, sockfd, connfd;
int nready, client[FD_SETSIZE];
ssize_t n ;
fd_set rset, allset;
char buf[MAXLINE];
struct sockaddr_in servaddr, chiladdr;
socklen_t chlien;
pid_t pid;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// inet_pton(AF_INET, INADDR_ANY, &servaddr.sin_addr);
Bind(sockfd, (SA *)&servaddr, sizeof(servaddr));
Listen(sockfd, LISTENQ);
// signal(SIGCHLD, sig_chld);
maxfd = sockfd;
maxi = -1;
for(i = 0; i < FD_SETSIZE; i++)
{
client[i] = -1;
}
FD_ZERO(&allset);
FD_SET(sockfd, &allset);
for(;;)
{
rset = allset;
printf("i walk here \n");
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
printf("nready:%d\n", nready);
if(FD_ISSET(sockfd, &rset))
{
chlien = sizeof(chiladdr);
if(( connfd = Accept(sockfd, (SA *)&chiladdr, &chlien )) < 0)
{
perror("accept error");
}
printf("new client: %d\n", inet_ntoa(chiladdr.sin_addr));
printf("new client port: %d\n", ntohs(chiladdr.sin_port));
for(i = 0; i < FD_SETSIZE; i++)
{
if(client[i] < 0)
{
client[i] = connfd;
break;
}
}
if(i == FD_SETSIZE)
{
perror("too many clients");
}
printf("connfd: %d\n", connfd);
FD_SET(connfd, &allset);
if(connfd > maxfd)
{
maxfd = connfd;
}
if(i > maxi)
{
maxi = i;
}
if(--nready <= 0 )
{
continue;
}
}
printf("i walk down here \n");
for( i = 0 ; i <= maxi; i++)
{
if( (listenfd = client[i]) < 0)
{
continue;
}
if(FD_ISSET(listenfd, &rset))
{
if( (n = read(listenfd, buf, MAXLINE)) == 0 )
{
Close(listenfd);
FD_CLR(listenfd, &allset);
client[i] = -1;
}
else
{
Writen(listenfd, buf, n);
}
if( --nready < 0 )
{
continue;
}
}
}
}
return 0;
}
then
gcc -o tcpserv05 -g sockheader.c tcpserv05.c
gcc -o tcpcli05 -g sockheader.c tcpcli05.c
./tcpserv05
./tcpcli05 127.0.0.1
in the cli, i input some thing like "hi, test". the serv do not return anything .
i gdb tcpserv05 then found the nready is always 1 . so --nready <= 0 is true, continue.
program did not go to below.
i need some help, thank you first.
#
I find the problem.
I wrote the wrong code :
read(stdin, buf, MAXLINE)
stdin is FILE * , fread、fwrite、fclose will use stdin.
ssize_t read(int fd, void *buf, size_t count);
so i use fileno(stdin) instead, program worked.
select returns 1, because that is the number of file descriptors that have events. If you had a timeout, it would return 0, if more file descriptors had events, it would return a higher number.
You might want to use poll(2) instead of the older select(2). Read about the C10K problem.
Since select may modify its fd_set bitmasks, you should set them inside the loop (often, fd_set is just an array, so assigning rset = allset; don't do what you want).
Don't forget to call fflush(3) at appropriate places (e.g. fflush(NULL) before any select or poll)
Consider also using strace(1) for debugging.
Always test every syscalls(2) for failure (using perror)
See comments for this related question.
Always compile with gcc -Wall -Wextra -g and improve your source code till you get no warnings at all. BTW, bzero(3) is explicitly deprecated (i.e. obsolete) and you should not use it.
Basically i'm trying to do a server-client program that communicates with sockets.
I find it strange that the server, once started it doesn't even print the first line. Why is this?
There must be something that's sliping from me and I really need to know what.
Server.c
int rvsock;
void stop(int sig){
close(rvsock);
}
void* worker(void* p){
struct mymsg m;
int err;
int sock = (int)p;
err = recv(sock,&m,sizeof(m),0);
if(err < 0){
printf("Failed to receive");
exit(1);
}
m.a = ntohl(m.a);
m.b = ntohl(m.b);
m.c = ntohl(m.c);
m.ip = ntohl(m.ip);
printf("Received numbers: %d %d %d from IP:%d", m.a,m.b,m.c,m.ip);
if(m.a < m.b && m.b <= m.c)
m.a = m.c;
else if(m.a < m.b && m.b >= m.c)
m.a = m.b;
else if(m.a > m.b && m.b <= m.c)
m.a = m.a;
m.a = htonl(m.a);
m.b = htonl(m.b);
m.c = htonl(m.c);
err = send(sock, &m,sizeof(m),0);
if(err < 0){
printf("Failed to send!");
close(sock);
return NULL;
}
close(sock);
return NULL;
}
int main(int argc, char** argv) {
printf("DAFUQ"); //It doesn't even print this. Why?
int port;
int sock;
int err;
unsigned int len;
struct sockaddr_in saddr;
struct sockaddr_in caddr;
pthread_t w[100];
int wn = 0;
int i;
sscanf(argv[1], "%d", &port);
signal(SIGINT, stop);
rvsock = socket(AF_INET, SOCK_STREAM, 0);
if(rvsock < 0) {
perror("Failed to create socket");
exit(1);
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons(port);
err = bind(rvsock, (struct sockaddr*)&saddr,
sizeof(struct sockaddr_in));
if(err < 0) {
perror("Failed to bind");
exit(1);
}
err = listen(rvsock, 5);
if(err < 0) {
perror("Failed to listen");
close(rvsock);
exit(1);
}
while(1) {
len = sizeof(struct sockaddr_in);
sock = accept(rvsock, (struct sockaddr*)&caddr, &len);
if(sock < 0) {
perror("Failed to accept");
break;
}
pthread_create(&w[wn], 0, worker, (int*)sock);
wn++;
}
for(i=0; i<wn; i++) {
pthread_join(w[i], 0);
}
return 0;
}
client.c
int main(int argc, char** argv){
int sock;
int err;
int port;
struct sockaddr_in saddr;
struct mymsg m;
sscanf(argv[1], "%d", &port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("failed to create");
exit(1);
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(port);
err = connect(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
if(err < 0){
perror("Failed to connect!");
exit(1);
}
printf("give a:");scanf("%d",&m.a);
printf("give b:");scanf("%d",&m.b);
printf("give c:");scanf("%d",&m.c);
m.a = htonl(m.a);
m.b = htonl(m.b);
m.c = htonl(m.c);
send(sock,&m,sizeof(m),0);
return 0;
}
message.h
struct mymsg{
int a;
int b;
int c;
int ip;
};
In your server you have this line. printf prints to the stdout FILE which is opened for you when you start your program.
printf("DAFUQ"); //It doesn't even print this. Why?
man stdout provides the following information about stdout:
The stream stdout is line-buffered
when it points to a terminal. Partial lines will not appear until
fflush(3) or exit(3) is called, or a newline is printed.
You don't print a newline, you don't flush stdout and your program doesn't exit, therefore none of the conditions required to print your output to the terminal are met.
Therefore in order to print the line you have 3 options:
1
printf("DAFUQ"); //It doesn't even print this. Why?
fflush(stdout);
2
printf("DAFUQ\n"); /*notice added '\n'*/
3
call exit() after you print ( not very helpful probably).