-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.c
More file actions
183 lines (159 loc) · 5.22 KB
/
client.c
File metadata and controls
183 lines (159 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//Eugene Li - Multithreaded chat client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#define MAX_BUFFER 1024
void chatloop(char *name, int socketFd);
void buildMessage(char *result, char *name, char *msg);
void setupAndConnect(struct sockaddr_in *serverAddr, struct hostent *host, int socketFd, long port);
void setNonBlock(int fd);
void interruptHandler(int sig);
static int socketFd;
int main(int argc, char *argv[])
{
char *name;
struct sockaddr_in serverAddr;
struct hostent *host;
long port;
if(argc != 4)
{
fprintf(stderr, "./client [username] [host] [port]\n");
exit(1);
}
name = argv[1];
if((host = gethostbyname(argv[2])) == NULL)
{
fprintf(stderr, "Couldn't get host name\n");
exit(1);
}
port = strtol(argv[3], NULL, 0);
if((socketFd = socket(AF_INET, SOCK_STREAM, 0))== -1)
{
fprintf(stderr, "Couldn't create socket\n");
exit(1);
}
setupAndConnect(&serverAddr, host, socketFd, port);
setNonBlock(socketFd);
setNonBlock(0);
//Set a handler for the interrupt signal
signal(SIGINT, interruptHandler);
//printf("%s", name);/////////////
chatloop(name, socketFd);
}
//Main loop to take in chat input and display output
void chatloop(char *name, int socketFd)
{
fd_set clientFds;
char chatMsg[MAX_BUFFER];
char chatBuffer[MAX_BUFFER], msgBuffer[MAX_BUFFER];
int flag=1;
while(1)
{
//Reset the fd set each time since select() modifies it
FD_ZERO(&clientFds);
FD_SET(socketFd, &clientFds);
FD_SET(0, &clientFds);
if(select(FD_SETSIZE, &clientFds, NULL, NULL, NULL) != -1) //wait for an available fd
{
for(int fd = 0; fd < FD_SETSIZE; fd++)
{
if(FD_ISSET(fd, &clientFds))
{
if(flag){
flag = 0;
write(socketFd,name,MAX_BUFFER-1); //////////////////
}
if(fd == socketFd) //receive data from server
{
int numBytesRead = read(socketFd, msgBuffer, MAX_BUFFER - 1);
msgBuffer[numBytesRead] = '\0';
printf("%s", msgBuffer);
memset(&msgBuffer, 0, sizeof(msgBuffer));
}
else if(fd == 0) //read from keyboard (stdin) and send to server
{
fgets(chatBuffer, MAX_BUFFER - 1, stdin);
if(strcmp(chatBuffer, "/exit\n") == 0)
interruptHandler(-1); //Reuse the interruptHandler function to disconnect the client
else if(strcmp(chatBuffer, "/user\n") == 0){
write(socketFd, "/user\n", MAX_BUFFER - 1);
}
else if(strncmp(chatBuffer, "/to ",3) == 0){
char* delim = " ";
char* pch = strtok(chatBuffer,delim);
char* pch2;
for(int i=1;i>0;i--){
pch = strtok(NULL,delim);
}
fprintf(stderr,"%s",pch);
pch2 = strtok(NULL,delim);
write(socketFd, "/to\n", MAX_BUFFER - 1);
//read(socketFd,msgBuffer, MAX_BUFFER - 1);//to who
// fprintf(stderr,"%s",msgBuffer);
write(socketFd,pch , MAX_BUFFER - 1);//2
read(socketFd,msgBuffer, MAX_BUFFER - 1);//3
write(socketFd, pch2, MAX_BUFFER - 1);
//fprintf(stderr,"%s",msgBuffer);
//write(socketFd, msgBuffer, MAX_BUFFER - 1);//4
}
else
{
buildMessage(chatMsg, name, chatBuffer);
if(write(socketFd, chatMsg, MAX_BUFFER - 1) == -1) perror("write failed: ");
//printf("%s", chatMsg);
memset(&chatBuffer, 0, sizeof(chatBuffer));
}
}
}
}
}
}
}
//Concatenates the name with the message and puts it into result
void buildMessage(char *result, char *name, char *msg)
{
memset(result, 0, MAX_BUFFER);
strcpy(result, name);
strcat(result, ": ");
strcat(result, msg);
}
//Sets up the socket and connects
void setupAndConnect(struct sockaddr_in *serverAddr, struct hostent *host, int socketFd, long port)
{
memset(serverAddr, 0, sizeof(serverAddr));
serverAddr->sin_family = AF_INET;
serverAddr->sin_addr = *((struct in_addr *)host->h_addr_list[0]);
serverAddr->sin_port = htons(port);
if(connect(socketFd, (struct sockaddr *) serverAddr, sizeof(struct sockaddr)) < 0)
{
perror("Couldn't connect to server");
exit(1);
}
}
//Sets the fd to nonblocking
void setNonBlock(int fd)
{
int flags = fcntl(fd, F_GETFL);
if(flags < 0)
perror("fcntl failed");
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
}
//Notify the server when the client exits by sending "/exit"
void interruptHandler(int sig_unused)
{
if(write(socketFd, "/exit\n", MAX_BUFFER - 1) == -1)
perror("write failed: ");
close(socketFd);
exit(1);
}