Tag: input int string cannot main char* argv ready hint
Cleint:
#define _gnu_source 1#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <string.h > #include <stdlib.h> #include <poll.h> #include <fcntl.h> #define BUFFER_SIZE int main (int argc, C har* argv[]) {if (argc <= 2) {printf ("Usage:%s ip_address port_number\n", basename (Argv[0])); return 1; } const char* IP = argv[1]; int port = atoi (argv[2]); struct sockaddr_in server_address; Bzero (&server_address, sizeof (server_address)); server_address.sin_family = af_inet; Inet_pton (Af_inet, IP, &server_address.sin_addr); Server_address.sin_port = htons (port); int SOCKFD = socket (pf_inet, sock_stream, 0); ASSERT (sockfd >= 0); Here's use block mode connect socket, there'll be minutes timeout if failed. if (Connect (sockfd, struct sockaddr*) &server_address, sizeof (server_address)) < 0) {printf ("Connection failed\n"); Close (SOCKFD); return 1; } POLLFD fds[2]; FDS[0].FD = 0; stdin fds[0].events = Pollin; fds[0].revents = 0; FDS[1].FD = SOCKFD; Why don ' t concern about Pollout event? fds[1].events = Pollin | Pollrdhup; Concern Read & Hangup event fds[1].events = Pollin | Pollrdhup | Pollout; fds[1].revents = 0; Char Read_buf[buffer_size]; int pipefd[2]; int ret = pipe (PIPEFD); ASSERT (Ret! =-1); while (1) {ret = poll (FDS, 2,-1); if (Ret < 0) {printf ("poll failure\n"); Break }//connection is hang-up by peer if (fds[1].revents & pollrdhup) {printf ("Server Close the connection\n "); Break }//have data from server to read else if (Fds[1].revents & Pollin) {memset(Read_buf, ' buffer_size '); Recv (FDS[1].FD, Read_buf, buffer_size-1, 0); printf ("Recv data from server:%s\n", read_buf); } else if (Fds[1].revents & pollout) {//always writable, would print so much a message, so Comm ENT It//printf ("Connection got Pollout event, it is writable now.\n"); } if (Fds[0].revents & Pollin)//user input--stdin has data to read {//stdin- PIPEFD[1] ret = splice (0, NULL, pipefd[1], NULL, 32768, Splice_f_more | Splice_f_move); PIPEFD[1]-pipefd[0]-SOCKFD ret = splice (pipefd[0], NULL, SOCKFD, NULL, 32768, Splice_f_more | Splice_f_move); }} close (SOCKFD); return 0;}
Server
#define _gnu_source 1#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h > #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <poll.h> #define User_ LIMIT 5#define buffer_size 64#define fd_limit 65535 struct client_data{sockaddr_in address; char* Write_buf; Char buf[buffer_size]; Client_data (): Write_buf (0) {}}; int setnonblocking (int fd) {int old_option = Fcntl (fd, F_GETFL); int new_option = Old_option | O_nonblock; Fcntl (FD, F_SETFL, new_option); return old_option;} int main (int argc, char* argv[]) {if (argc <= 2) {printf ("Usage:%s ip_address port_number\n", Basena Me (argv[0]); return 1; } const char* IP = argv[1]; int port = atoi (argv[2]); int ret = 0; struct SOCKADDR_IN address; Bzero (&address, sizeof(address)); address.sin_family = af_inet; Inet_pton (Af_inet, IP, &address.sin_addr); Address.sin_port = htons (port); int LISTENFD = socket (pf_inet, sock_stream, 0); ASSERT (LISTENFD >= 0); ret = bind (LISTENFD, (struct sockaddr*) &address, sizeof (address)); ASSERT (Ret! =-1); RET = Listen (LISTENFD, 5); Backlog=5 assert (Ret! =-1); client_data* users = new Client_data[fd_limit]; POLLFD fds[user_limit+1]; 1 Listen sock FD + 5 user sock fd int user_counter = 0; for (int i = 1; I <= user_limit; ++i) {fds[i].fd =-1; fds[i].events = 0; } FDS[0].FD = LISTENFD; fds[0].events = Pollin | Pollerr; Read & Error Event fds[0].revents = 0; while (1) {ret = poll (FDS, user_counter+1,-1); if (Ret < 0) {printf ("poll failure\n"); Break } for (int i = 0; i < user_counter+1; ++i) {//CLIENT call connect to this server if ((FDS[I].FD = = LISTENFD) && (fds[i].revents & Pollin)) {struct sockaddr_in client_address; socklen_t client_addrlength = sizeof (client_address); LISTENFD is block mode by default, but use poll we know the event is ready, accept'll return right now int CONNFD = Accept (LISTENFD, (struct sockaddr*) &client_address, &client_addrlength); if (CONNFD < 0) {printf ("Accept errno is:%d\n", errno); Continue } if (User_counter >= user_limit) {Const char* info = "Too many use RS, so close this connfd returned by accept.\n "; printf ("%s", info); Send (CONNFD, info, strlen (info), 0); Close (CONNFD); Continue } user_counter++; users[connfd].address = client_address; Setnonblocking (CONNFD); CONNFD is Nonblock mode fds[user_counter].fd = CONNFD; fds[user_counter].events = Pollin | Pollrdhup | pollerr;//concern about Read & Hanguo & Error event at start fds[user_counter].revents = 0; printf ("comes a new user, now has%d users\n", user_counter); } else if (Fds[i].revents & Pollerr)//fds[i] has error! {printf ("Get an error from%d\n", FDS[I].FD); Char errors[100]; memset (Errors, ' 100 '); socklen_t length = sizeof (errors); if (getsockopt (FDS[I].FD, Sol_socket, So_error, &errors, &length) < 0) {p rintf ("Get socket Option failed\n"); } else printf ("%d got an ERror%s\n ", FDS[I].FD, errors); Continue } else if (Fds[i].revents & Pollrdhup)//fds[i] was hang up by peer {users[fds[ I].FD] = USERS[FDS[USER_COUNTER].FD]; Close (FDS[I].FD); Fds[i] = Fds[user_counter]; i--; user_counter--; printf ("A client left\n"); }//got Readable event else if (Fds[i].revents & pollin) {int CONNFD = FDS[I].FD; memset (users[connfd].buf, ' buffer_size '); ret = recv (CONNFD, Users[connfd].buf, buffer_size-1, 0); printf ("Get%d bytes of client data:%s from connection:%d\n", ret, Users[connfd].buf, CONNFD); if (Ret < 0)//has error {//nonblock socket, the Read function returns an error eagain, prompting your application to now have no data to read please slightly And then try again. If it is a eagain error we just IGnore This error and wait for next Pollin event if (errno! = Eagain) { Close (CONNFD); USERS[FDS[I].FD] = USERS[FDS[USER_COUNTER].FD]; Fds[i] = Fds[user_counter]; i--; user_counter--; printf ("recv data from a client-ran into error, a client maybe left\n"); }}//if the connection has been gracefully closed and the return value is zero. else if (ret = = 0) {//printf ("code should not come to here\n"); printf ("recv function return 0 indicates the client has gracefully closed and exit.\n"); Need to remove it from FDS?? } else//server send the data recv from a client to all other clients { for (int j = 1; J <=User_counter; ++J) {if (fds[j].fd = = CONNFD) { Continue Don ' t send to self}//Other client's socket is no longer readable at the moment (current Client continues to send multiple messages, these messages will be blocked in the socket Sendbuffer),//To be set to only write! Because if you can read it again, if the client sends multiple messages consecutively, the other client will miss the following message! Fds[j].events |= ~pollin; Fds[j].events |= pollout; Users[fds[j].fd].write_buf = Users[connfd].buf; }}} and Else if (Fds[i].revents & pollout)//got writable Event { int connfd = FDS[I].FD; if (! Users[connfd].write_buf) {continue;//no data Send to this client } ret = Send (CONNFD, Users[connfd].write_buf, strlen (USERS[CONNFD].WRITE_BUF), 0); USers[connfd].write_buf = NULL; Reset back fds[i].events |= ~pollout; Fds[i].events |= Pollin; }}} Delete [] users; Close (LISTENFD); return 0;}
Linux Socket Talkclient Talkserver example