📄 c.c
字号:
/*
c.c A chat client from Ze Zhang and Johannes Detlefsen
compile: gcc -o c c.c -lncurses -lpthread
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h> // for the inet_ntoa() function
#include <sys/socket.h> // for a convenient realization of IPC
#include <ncurses.h> /* for the nice windows */
#include <pthread.h> // for the cosy POSIX threads
#define PORT 9034 // the port client will be connecting to
#define WWW "www.tec.hkr.se"
#define MAXLEN 100 // max number of bytes we can get at once
#define MAX 10 // max number of chars in username string
void * readmsg(void * arg);
void * writemsg(void * arg);
int sockfd;
WINDOW *win_read;
WINDOW *win_write;
//WINDOW *win_usrs; // not implemented function of online user's names display
void loginwin(){
WINDOW *win_login;
int h,w,usernamelength;
char username[MAX]=" \0", *usr;
initscr();
cbreak();
refresh();
getmaxyx(stdscr,h,w);
win_login = newwin(3,19,h/2-3,w/2-10);
box(win_login,0,0);
mvwprintw(win_login,1,1,"login: ");
wrefresh(win_login);
mvwgetnstr(win_login,1,8,username,MAX);
(char *) usr = username;
usernamelength = strlen(username);
send(sockfd,usr,usernamelength,0);
wrefresh(win_login);
delwin(win_login);
}
void chatwin(){
int h,w;
WINDOW *win_box;
getmaxyx(stdscr,h,w);
win_box = newwin(h-6,w,1,0);
box(win_box,0,0);
mvwprintw(win_box,0,5," Output Window ");
wrefresh(win_box);
win_read = newwin(h-8,w-2,2,1);
scrollok(win_read,TRUE);
wrefresh(win_read);
win_write = newwin(3,w,h-5,0);
box(win_write,0,0);
mvwprintw(win_write,0,5," Input Window ");
mvwprintw(win_write,0,20," type /q to exit ");
wrefresh(win_write);
/*win_usrs = newwin(h-6,20,1,w-20);
box(win_usrs,0,0);
scrollok(win_usrs,TRUE);
mvwprintw(win_usrs,0,2," Users Online ");
wrefresh(win_usrs);*/
}
int main( int argc, char *argv[] )
{
struct hostent *he;
struct sockaddr_in server_addr; // connector's address information
int portnum;
pthread_t thread_id1;
pthread_t thread_id2;
/* if portnumber is not given by argument use defined (9034) */
if( argc == 2 ) portnum = atoi(argv[1]);
else portnum = PORT;
if ((he=gethostbyname(WWW)) == NULL) { // get the host info
perror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
//else printf("The Socket was created\n");
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(portnum); // short, network byte order
server_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(server_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
if(initscr()==NULL){ // initialize ncurses WINDOW (stdscr)
printf("could not initialize ncurses Window");
exit(1);
}
printw("client connected to %s\n",inet_ntoa(server_addr.sin_addr));
loginwin(); // input username and send it to server
chatwin(); // initialize chat windows
pthread_create(&thread_id1,NULL,readmsg,NULL);
pthread_create(&thread_id2,NULL,writemsg,NULL);
pthread_join(thread_id1,NULL);
pthread_join(thread_id2,NULL);
/* since the socket file descriptor is full duplex
there is no need to protect him with mutex */
close(sockfd);
return 0;
}
void * readmsg(void * arg){
char buf[MAXLEN];
int numbytes;
wmove(win_read,0,0);
while(1){ // loop to constantly recv and read msgs, terminated by exit in writemsg()
/*if ((numbytes=recv(sockfd, buf, MAXLEN-1, 0)) == -1) {
perror("recv");
exit(1); }*/
if ( (numbytes=recv(sockfd, buf, MAXLEN-1, 0)) > 0 ) { // if message received print it out
buf[numbytes] = '\0';
wprintw(win_read,"%s\n",buf); //mvwprintw(win_read,y,1,"%s",buf);
wrefresh(win_read);
}
};
}
void * writemsg(void * arg){
int bufsize,i,h,w;
char *buffer = (char *) malloc(MAXLEN);
getmaxyx(stdscr,h,w);
//noecho();
while(1){ // loop to send msgs, terminated with exit by /q
for(i=18;i<=w-3;i++) mvwprintw(win_write,1,i," ");
wrefresh(win_write);
mvwprintw(win_write,1,1,"Message to send: ");
wrefresh(win_write);
mvwgetnstr(win_write,1,18,buffer,w-21); // read input msg
if ( strncmp( buffer, "/q", 2) == 0 ){ /* close and exit( 0 ) condition */
send(sockfd,"/q",2,0); // send /q termination msg to server
refresh();
delwin(win_read);
delwin(win_write);
//delwin(win_usrs);
endwin();
printf("terminating gracefully - goodbye and have a nice day!\n");
close(sockfd);
exit(0);
}
bufsize=strlen(buffer)+1;
send(sockfd,buffer,bufsize,0);
};
}
// Do we need a mutex protection for the socket-file-descriptor??? no because it's full duplex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -