Linux Socket Implementation of a Network Chat Room (Part 2): Independent Message Sending and Receiving Using Threads
#Socket#Linux#Chat#Networking#Struct#Null
1. Introduction
2. Code Implementation
1. Server Side
/*tcpserver.c 2011.9.1 by yyg*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#define MYPORT 3490 // Define port
#define BACKLOG 10
#define MAXDATASIZE 1024
int sockfd, new_fd;
pthread_t accthread, recthread;
void recmessage(void) { // Function to receive client messages
while(1) {
int numbytes;
char buf[MAXDATASIZE];
if ((numbytes = recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
if (strcmp(buf, "exit") == 0) { // If received message is "exit", terminate communication
printf("Client is closed\n");
close(new_fd);
close(sockfd);
exit(1);
}
printf("client:%s\n", buf);
} /*while*/
}
void acceptconnect(void) { // Function to accept client connection requests
struct sockaddr_in their_addr;
int sin_size;
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
exit(1);
}
printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
/* Create child thread for receiving messages */
if ((pthread_create(&recthread, NULL, (void*)recmessage, NULL)) != 0) {
printf("create thread error!\r\n");
exit(1);
}
}
int main(void) {
struct sockaddr_in my_addr;
/* Create socket */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* Initialize parameters in sockaddr_in structure */
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
/* Bind port and socket */
if (bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
/* Listen for client socket connections */
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listening...\n");
/* Create child thread to accept connections */
if ((pthread_create(&accthread, NULL, (void*)acceptconnect, NULL)) != 0) {
printf("create thread error!\n");
exit(1);
}
while(1) {
char msg[MAXDATASIZE];
scanf("%s", msg);
if (send(new_fd, msg, strlen(msg), 0) == -1) { // Send message to communicate with client
perror("send");
exit(1);
}
if (strcmp(msg, "exit") == 0) {
printf("byebye\n");
close(new_fd);
close(sockfd);
exit(1);
}
} /*while*/
return 0;
} /*main*/
2. Client Side
/*tcpclient.c 2010.9.1 by yyg*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <netdb.h>
#define PORT 3490
#define BACKLOG 10
#define MAXDATASIZE 1024
int sockfd;
pthread_t recthread;
/* Function to receive messages */
void recmessage(void) {
while(1) {
int numbytes;
char buf[MAXDATASIZE];
if ((numbytes = recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
if (strcmp(buf, "exit") == 0) {
printf("Server is closed\n");
close(sockfd);
exit(1);
}
printf("Server:%s\n", buf);
} /*while*/
}
int main(int argc, char *argv[]) {
struct hostent *he;
struct sockaddr_in their_addr;
/* Client input format: ./client 172.31.100.236
If IP address is not provided, an error will be shown */
if (argc != 2) {
fprintf(stderr, "usage: client hostname\n");
exit(1);
}
/* Get host IP address */
if ((he = gethostbyname(argv[1])) == NULL) {
herror("gethostbyname");
exit(1);
}
/* Create socket */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* Initialize sockaddr_in structure */
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8);
/* Send connection request to server */
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
/* Create child thread for receiving messages */
if ((pthread_create(&recthread, NULL, (void*)recmessage, NULL)) != 0) {
printf("create thread error!\r\n");
exit(1);
}
/* Send messages. The same socket (sockfd) is used for both sending and receiving */
while(1) {
char msg[MAXDATASIZE];
scanf("%s", msg);
if (send(sockfd, msg, strlen(msg), 0) == -1) {
perror("send");
exit(1);
}
if (strcmp(msg, "exit") == 0) {
printf("byebye\n");
close(sockfd);
exit(1);
}
} /*while*/
return 0;
}
Execution Results:
Terminal 1:
[root@localhost net]# ./tcpserver
server:got connection from 172.31.100.236
Hello,World!
client:hello
client:xiaolian
client:iou
ok
exit
byebye
Terminal 2:
[root@localhost net]# ./tcpclient 172.31.100.236
Server:Hello,World!
hello
xiaolian
iou
Server:ok
Server is closed