I'm building a server that listens on multiple ports for multiple clients to connect to. I'm using threads to handle each of these connections. However, when > 2 clients connect to a port the server doesn't handle the following connections. Not sure if it's a connection issue or a thread issue. New to both.
/** Thread started by the client that has connected
*
*
*
*/
void* client_listener(void* client){
printf("Client for thread started\n");
fflush(stdout);
return NULL;
}
/** Listen for clients for this game
*
*
*
*/
void* listen_now(void* gameStruct){
Game* thisGame = (Game*) gameStruct;
listen(thisGame->sockfd, thisGame->totalPlayers);
int playerAdded = 0;
struct sockaddr_in cli_address;
socklen_t clilen = sizeof(cli_address);
//Keep accepting new connections
while((accept(thisGame->sockfd, (struct sockaddr*) &cli_address, &clilen) > 0)){
//Make the player in the game
printf("Total Players accepted is %d\n", playerAdded);
fflush(stdout);
//Make a client to store in the game struct
Client* thisPlayer = make_client(thisGame, thisGame->clientSockfd[thisGame->gameId]);
thisPlayer->cli_address = cli_address;
//Save values to this Client
thisPlayer->id = playerAdded;
pthread_t clientThread = thisPlayer->clientThread;
//Create thread for this client
pthread_create(&clientThread, NULL, client_listener, &thisPlayer);
playerAdded++;
}
}
/** Get the socket for the port
*
*
*/
int get_socket_for_port(Game* game, int port){
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
game->server_address.sin_family = AF_INET;
game->server_address.sin_port = htons(port);
game->server_address.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*) &game->server_address, sizeof(game->server_address))<0){
printf("bind failed");
}
return sockfd;
}
/** Setup the game threads
*
*
*/
void setup_game(Server* server){
pthread_t gameThreads[server->numberOfGames-1];
Game* traversal = server->game;
int gameId;
//Loop through the games and setup their ports to listen on
while(traversal!=NULL){
traversal->clientSockfd = (int*) malloc(traversal->totalPlayers*sizeof(int));
//Get the sockfd for the port
int sockfd = get_socket_for_port(traversal, traversal->port);
//Save the socketfd for this game to struct
traversal->gameId = gameId;
traversal->sockfd = sockfd;
//Create a gameThread
pthread_create(&gameThreads[gameId], NULL, *listen_now, traversal);
gameId++;
traversal = traversal->nextGame;
}
}
When I connect 4 times to ports the server is listening on. I get the following output. Not sure, and interested in learning what might be going on.
Output:
Total Players accepted is 0
Client thread started
Total Players accepted is 1
Client thread started
Total Players accepted is 2
Related
I want to take a message from one client and send it to the other with a server in middle.
I use the select function to make several connections to the server possible but here is the problem:
I store the socket descriptor sock in Queue[pq] using dup and it's working. the sock = 4 & Queue[0] = 5. now I need to take the other client's socket descriptor, and again I store it in Queue. the values of Queue for Client(2) equals to Queue[0] = 5 , Queue[1] = 7 but for the first client it's still Queue[0] = 5 and Queue[1] = 0 it means the code for first client doesn't have access to the second client's socket descriptor and i cant forward it to the other client using his socket descriptor with send() and client 3 has the the first 2 client's socket descriptor but the first 2 client doesn't have the third one's socket descriptor.
I think that's because select() use different memory address for the values for each client just like sock which has different values for each connection.
how I can solve this problem? how the clients can access each other's socket descriptor?
the code:
Global Values:
int tcpfd, udpfd, Sock, nready, maxfdp1;
int Queue[64];
int pq = -1;
int max(int x, int y) {
if (x > y)
return x;
else
return y;
}
int main(){
pid_t childpid;
fd_set rset;
ssize_t n;
socklen_t len;
const int on = 1;
struct sockaddr_in cliaddr, servaddr;
void sig_chld(int);
/* create listening TCP socket */
tcpfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.1.5");
servaddr.sin_port = htons(PORT);
// binding server addr structure to tcpfd
bind(tcpfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
listen(tcpfd, 10);
// clear the descriptor set
// get maxfd
maxfdp1 = max(tcpfd, udpfd) + 1;
for (;;) {
// set tcpfd and udpfd in readset
FD_ZERO(&rset);
FD_SET(tcpfd, &rset);
// select the ready descriptor
nready = select(maxfdp1, &rset, NULL, NULL, NULL);
// if tcp socket is readable then handle
// it by accepting the connection
if (FD_ISSET(tcpfd, &rset)){
len = sizeof(cliaddr);
Sock = accept(tcpfd, (struct sockaddr*)&cliaddr, &len);
pq++;
Queue[pq] = dup(Sock);
printf("%d\n",Sock);
if ((childpid = fork()) == 0) {
Access_Request();
while(1) { //rest of the code
}
I am new to C language, and when I used c to write a socket program, I encountered a problem.
I want to implement two-way communication between two computers (Linux and Simulink). In Linux, I need to implement a connection-based UDP client and server. And for other needs, I divided the process of creating UDP communication into four parts: creating the sender socket, server binding process, sending data and accepting data.
The code is compiled successfully. During the run, the value can be successfully sent to Simulink, but it is blocked on the 'recv()' function. I used Wireshark to view the data packets of the computer where Simulink is located. The data packets of this computer are normal. In other words, the socket in Linux received the datagram, but my program could not read it.
The code in Linux is as below:
void check_comm_error(int ret);// just for check error
void sendsock_creat(); //creat socket and server ip address
void sendsock_send(void* send_buf); //call send function and send data
void recvsock_creat(); called by sendsock_creat function
void recvsock_recv(); just for receieve data
int client_fd; //定义套接字描述符
double senddata[1] = {10};
double recvdata[1];
struct sockaddr_in local_addr;//定义本地地址 <netinet/in.h>
void sendsock_creat()
{
int check_ret = 0;//定义操作返回值,以传给check_comm_error函数
struct sockaddr_in server_addr;//定义服务器地址 <netinet/in.h>
int ser_addr_len;//定义服务端地址长度
client_fd = socket(AF_INET, SOCK_DGRAM, 0); //创建客户端套接字
check_ret = client_fd;
check_comm_error(check_ret);//判断是否出错
recvsock_creat();//Need to run the bind function before connect function
memset(&server_addr, 0, sizeof(server_addr)); //清空服务器地址结构体
server_addr.sin_family = AF_INET; //定义地址中的地址类型
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);//给出服务端的ip地址
server_addr.sin_port = htons(SERVER_PORT); //
check_ret=connect(client_fd, (struct sockaddr*)&server_addr,
sizeof(server_addr)); //连接服务端
check_comm_error(check_ret);//判断是否出错
}
void sendsock_send(void* send_buf)
{
//void* send_buf 为待发送的数据缓冲区
int check_ret = 0;
check_ret = send(client_fd, send_buf, sizeof(send_buf), 0);
check_comm_error(check_ret);
}
void check_comm_error(int ret)
{
if(ret < 0)
{
perror("create socket fail!\n");
exit(1);
}
}
void recvsock_creat()
{
int check_ret = 0;//定义操作返回值,以传给check_comm_error函数
int recv_flag; //接受标志
int ser_addr_len;//定义本地地址长度
memset(&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family=AF_INET;//bind to a local port
local_addr.sin_addr.s_addr=htonl(INADDR_ANY);
local_addr.sin_port=htons(LOCAL_PORT);
check_ret = bind(client_fd,(struct sockaddr *)&local_addr, sizeof(struct
sockaddr_in));
check_comm_error(check_ret);
recv(client_fd, recvdata, sizeof(recvdata), 0); //This function can get
the right value
printf("recv from simulink %f \n", recvdata[0]);
}
void recvsock_recv()
{
int recv_flag;
int addr_len;
recv_flag = recv(client_fd, recvdata, sizeof(recvdata),0);
}
int main()
{
sendsock_creat();
sendsock_send((double *)senddata);
recvsock_recv();
printf("recv from matlab %f .\n",recvdata[0]);
return 0;
}
Because the program has been compiled, the head file part is definitely no problem, So I ignore the include that part.
I am attempting to make a game of Minesweeper where multiple players can access the server to play the game. I am struggling with using Pthreads to allow multiple connections to the game at the same time. The program starts in my main method, it then calls setup_listener then calls get_clients. I am new to pthreads and socket programming, my understanding is that for every new client added a new thread should be created. The method authenticate_process is used to check the clients username and password. Currently once i use pthread_create my game logic begins with the function menu_option passing it the current clients socket. When i run my first new client my program works perfectly however once i start a second client my program is stuck idling. Could someone please show or explain to me where/what needs to be done to fix my problem.
/* Global Variables */
int num_conn = 0;
int player_count = 0;
pthread_mutex_t mutexcount;
/*
* Main Program
*/
int main(int argc, char *argv[])
{
int port;
/* Make sure a port was specified. */
if (argc < 2) {
fprintf(stderr,"No port provided using port 12345\n");
port = 12345;
}
else {
port = atoi(argv[1]);
}
int lis_sockfd = setup_listener(port); /* Listener socket. */
pthread_mutex_init(&mutexcount, NULL);
while (1) {
int *cli_sockfd = (int*)malloc(2*sizeof(int)); /* Client sockets */
memset(cli_sockfd, 0, 2*sizeof(int));
/* Get clients connected. */
get_clients(lis_sockfd, cli_sockfd);
pthread_t thread; /* Don't really need the thread id for anything in this case, but here it is anyway. */
int result = pthread_create(&thread, NULL, menu_option, (void *)cli_sockfd); /* Start a new thread for this game. */
if (result){
printf("Thread creation failed with return code %d\n", result);
exit(-1);
}
printf("[DEBUG] New game thread started.\n");
}
close(lis_sockfd);
pthread_mutex_destroy(&mutexcount);
pthread_exit(NULL);
}
/* Sets up the listener socket. */
int setup_listener(int portno)
{
int sockfd;
struct sockaddr_in serv_addr;
/* Get a socket to listen on */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening listener socket.");
/* Zero out the memory for the server information */
memset(&serv_addr, 0, sizeof(serv_addr));
/* set up the server info */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Bind the server info to the listener socket. */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR binding listener socket.");
//printf("[DEBUG] Listener set.\n");
/* Return the socket number. */
return sockfd;
}
/* Sets up the client sockets and client connections. */
void get_clients(int lis_sockfd, int * cli_sockfd)
{
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/* Listen for clients. */
listen(lis_sockfd, 253 - player_count);
/* Zero out memory for the client information. */
memset(&cli_addr, 0, sizeof(cli_addr));
clilen = sizeof(cli_addr);
/* Accept the connection from the client. */
cli_sockfd[num_conn] = accept(lis_sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (cli_sockfd[num_conn] < 0)
/* Horrible things have happened. */
error("ERROR accepting a connection from a client.");
/* Send the client it's ID. */
write(cli_sockfd[num_conn], &num_conn, sizeof(int));
/* Authentication Process */
bool isauthenticated = authenticate_process(*cli_sockfd);
if (isauthenticated){
printf("Authenticated\n");
}
else {
printf("Not Authenticated\n");
}
/* Increment the player count. */
num_conn++;
pthread_mutex_lock(&mutexcount);
player_count++;
printf("Number of players is now %d.\n", player_count);
pthread_mutex_unlock(&mutexcount);
}
/* Runs a game clients. */
void *menu_option(void *thread_data)
{
int *cli_sockfd = (int*)thread_data; /* Client sockets. */
int gameoption = 0;
while(1){
gameoption = recv_int(*cli_sockfd);
printf("[DEBUG] User menu option: %d\n",gameoption);
while (gameoption == 1){
running_game(*cli_sockfd); // Run Game Logic
break;
}
while (gameoption == 2){
show_leaderboard(*cli_sockfd);
// Need to notify client to break and send menu option again
break;
}
}
printf("\nGame over.\n");
close(*cli_sockfd);
free(cli_sockfd);
pthread_exit(NULL);
}
I wrote a module for asterisk that needs to communicate to a service request information an return it, but for some reason my socket does not connect at all. When I telnet to the service it works fine, but I can not figure out why the it returns a -1 in the module
This is the code in my module
int SocketQuery(char buffer[BUFFSIZE],char *qrystr){
int sock;
struct sockaddr_in eserver;
int sockres = 0;
unsigned char receiving = 1;
memset(sendbuff,0,sizeof(sendbuff));
/* Create the TCP socket */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
ast_log(LOG_ERROR,"Failed to create socket for LCRROUTER");
return -1;
}
/* Construct the server sockaddr_in structure */
memset(&eserver, 0, sizeof(eserver)); /* Clear struct */
eserver.sin_family = AF_INET; /* Internet/IP */
eserver.sin_addr.s_addr = inet_addr(IP); /* IP address */
eserver.sin_port = htons(port); /* server port */
/* Establish connection */
ast_log(LOG_NOTICE,"LCRROUTER - Connection to %s on port %s\n", IP, port);
sockres = connect(sock,
(struct sockaddr *) &eserver,
sizeof(eserver));
if (sockres < 0) {
ast_log(LOG_ERROR,"LCRROUTER - Failed to connect with server on %s:%s. Error Code %d", IP,port,sockres);
return -1;
}
sockres returns -1. Do I miss something?
You can use
tcpdump port YOUR_PORT_HERE -v -s0
In that form it will show you all packets sent via socket.
I have a simple C program that's supposed to listen for connections and start a new thread for each client that connects. The thread simply prints what messages it receives (for now). I followed two tutorials while making this.
It works, but I tried connecting and disconnecting repeatedly with netcat without sending any messages. Each time I connect, the program takes 8KB of memory, but it only releases 4KB when I disconnect. But I can't find the cause of the leak. It ends the thread and closes the socket every time the user disconnects. Here is all of the code involved:
void* clientFunction(void* arg) {
char receiveBuffer[RECEIVE_BUFFER_SIZE];
long receiveSize;
int clntSocket = * ((int*) arg);
while (true) {
//receive messages
receiveSize = recv(clntSocket, receiveBuffer, RECEIVE_BUFFER_SIZE, 0);
if (receiveSize <= 0) {
close(clntSocket);
return NULL;
}
printf("Received message: %s", receiveBuffer);
memset(&receiveBuffer, 0, sizeof(receiveBuffer));
}
return 0;
}
int main(int argc, const char * argv[]) {
//FOR LISTENING SOCKET =====
int servSock; /* Socket descriptor for server */
int clntSock; /* Socket descriptor for client */
struct sockaddr_in serverAddress; /* Local address */
struct sockaddr_in clientAddress; /* Client address */
unsigned int clntLen; /* Length of client address data structure */
// =======
/* Create socket for incoming connections */
if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
printf("Socket creation failed!\n");
return SOCKET_ERROR;
}
memset(&serverAddress, 0, sizeof(serverAddress)); /* Zero out structure */
serverAddress.sin_family = AF_INET; /* Internet address family */
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
serverAddress.sin_port = htons(PORT); /* Local port */
if (bind(servSock, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
printf("Socket binding failed!\n");
return SOCKET_ERROR;
}
if (listen(servSock, MAXPENDING) < 0) {
printf("Socket listening failed!\n");
return SOCKET_ERROR;
}
isListening = true;
int* arg = &clntSock;
while (isListening) { //should have a timer?
/* Set the size of the in-out parameter */
clntLen = sizeof(clientAddress);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &clientAddress, &clntLen)) >= 0) { //??????
/* clntSock is connected to a client! */
pthread_t clientThread;
pthread_create(&clientThread, NULL, &clientFunction, (void*) arg);
}
}
return 0;
}
I put in pthread_detach(pthread_self()) right after the socket closing line, and it doesn't have the problem anymore. – sudo