1.简介
2.TCP客户端
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
using namespace std;
int main() {
//Create a socket For client to use TCP connect the Server
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd == -1) {
perror("Cannot Create a socket for TCP");
exit(EXIT_FAILURE);
}
//Set the client IP address and port
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(0);
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(client_addr.sin_zero,0,8);
//Bind the socket with IP address and port
if(bind(fd,reinterpret_cast<sockaddr *>(&client_addr),sizeof(client_addr)) == -1) {
perror("Cannot bind the socket");
exit(EXIT_FAILURE);
}
//Set the Server IP address and port
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(23333);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(server_addr.sin_zero,0,8);
//Try to Connect the server
if(connect(fd,reinterpret_cast<sockaddr *>(&server_addr),sizeof(server_addr)) == -1) {
perror("Cannot connect the server");
exit(EXIT_FAILURE);
}
while(true) {
string buf;
cin >> buf;
if(buf == "stop")
break;
if(write(fd,buf.c_str(),buf.length()) != buf.length()) {
perror("Something Wrong when write");
exit(EXIT_FAILURE);
}
}
close(fd);
}
3. TCP服务器
#include <iostream>
#include <set>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
using namespace std;
int main() {
//Create the server listen socket
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(listen_fd == -1) {
perror("Cannot Create a Socket For TCP");
exit(EXIT_FAILURE);
}
//Set the Server IP Address and port
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(23333);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_addr.sin_zero,0,8);
//Set the socket option with reuse address,Otherwise we cannot bind immediately after reboot
int is_reuse = 1;
if(setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&is_reuse,sizeof(int)) == -1) {
perror("Cannot Set socket option");
exit(EXIT_FAILURE);
}
// //Bind the socket with IP address and port
if(bind(listen_fd,reinterpret_cast<sockaddr *>(&server_addr),sizeof(server_addr)) == -1) {
perror("Cannot Bind the socket");
exit(EXIT_FAILURE);
}
//Start to listen in this socket
if(listen(listen_fd,5) == -1) {
perror("Cannot use the socket to listen");
exit(EXIT_FAILURE);
}
//Save the connected client information
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
//Server1:serial way,blocked IO,Interact with one client per time
// while(true) {
// char buf[1024];
// int connect_fd;
// if((connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length)) == -1) {
// perror("Cannot get a TCP connection");
// continue;
// }
// int n;
// while(n = read(connect_fd,buf,1024)) {
// if(n == -1) {
// perror("Error when read Data:");
// break;
// } else {
// memset(buf+n,0,1024-n);
// char addr_ip[INET_ADDRSTRLEN];
// inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
// fprintf(stderr, "Receive data from:%s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
// }
// }
// }
// close(listen_fd);
//Server2:serial,IO multiplexing with select,per second to choose an active socket to handle
// fd_set read_fds;
// FD_ZERO(&read_fds);
// set<int> all_fd;
// all_fd.insert(listen_fd);
// while(true) {
// struct timeval timeout = {1,0}; //select would change timeout value each time,we should reset it.
// for(auto it = all_fd.begin();it != all_fd.end();it++) { //select would change timeout value each time, we should reset it too.
// FD_SET(*it,&read_fds);
// }
// int result = select(*(all_fd.rbegin())+1,&read_fds,NULL,NULL,&timeout); //Blocked here until timeout or some socket can read
// if(result == -1) {
// perror("IO Error:");
// continue;
// } else if(result == 0) {
// continue;
// }
// if(FD_ISSET(listen_fd,&read_fds)) {
// int connect_fd;
// if((connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length)) == -1) { //would not block now,because it is ready.
// perror("Cannot get a TCP connection");
// continue;
// }
// char addr_ip[INET_ADDRSTRLEN];
// inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
// printf("Client %s:%d has connected to server\n",addr_ip,ntohs(client_addr.sin_port));
// FD_SET(connect_fd,&read_fds); //Add the new connect_fd monitored by select
// all_fd.insert(connect_fd);
// FD_CLR(connect_fd,&read_fds); //Clear the new connect_fd
// FD_CLR(listen_fd,&read_fds); //Clear the listen_fd after handle it
// }
// char buf[1024];
// for(auto it = all_fd.begin();it != all_fd.end();++it) {
// if(FD_ISSET(*it,&read_fds)) {
// int n = read(*it,buf,1024);
// char addr_ip[INET_ADDRSTRLEN];
// getpeername(*it,reinterpret_cast<sockaddr *>(&client_addr),&length); //Get the peer address by fd
// inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
// if(n == -1 || n == 0) {
// if(n == -1)
// perror("Error when read Data:");
// else
// printf("Client %s:%d has closed the connection\n",addr_ip,ntohs(client_addr.sin_port));
// close(*it);
// all_fd.erase(it);
// } else {
// memset(buf+n,0,1024-n);
// fprintf(stderr, "Receive data from:%s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
// }
// FD_CLR(*it,&read_fds);
// }
// }
// }
// close(listen_fd);
//server3:serial,IO multiplexing with epoll(More effective way),per second to choose an active socket to handle
int epoll_fd = epoll_create(1); //size is ignored in new version,simply set one positve interger is ok
if(epoll_fd == -1) {
perror("Cannot create epoll instance");
exit(EXIT_FAILURE);
}
int max_events = 20;
struct epoll_event listen_event;
struct epoll_event event_list[20];
listen_event.data.fd = listen_fd;
listen_event.events = EPOLLIN|EPOLLET; //Set the level triggered mode,
//If listenfd is ready,listen_event will be in event_list,we can check event_list to see either someone.data.fd is listen_fd.
if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_fd,&listen_event) == -1) {
perror("Cannot add listen fd:");
exit(EXIT_FAILURE);
}
while(true) {
int result = epoll_wait(epoll_fd,event_list,max_events,1000);
if(result == -1) {
perror("IO Error:");
continue;
} else if(result == 0) {
continue;
}
char buf[1024];
for(int i = 0;i < result;i++) { //The ready fds is in events[0,result).data.fd
if(listen_fd == event_list[i].data.fd) {
int connect_fd = accept(listen_fd,reinterpret_cast<sockaddr *>(&client_addr),&length);
if(connect_fd == -1) {
perror("Cannot get a TCP connection");
continue;
}
char addr_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip));
printf("Client %s:%d has connected to server\n",addr_ip,ntohs(client_addr.sin_port));
struct epoll_event read_event; //May debug here
read_event.data.fd = connect_fd;
read_event.events = EPOLLIN|EPOLLET;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,connect_fd,&read_event);
} else {
int connect_fd = event_list[i].data.fd;
int n = read(connect_fd,buf,1024);
getpeername(connect_fd,reinterpret_cast<sockaddr *>(&client_addr),&length); //Get the peer address by fd
char addr_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET,&client_addr.sin_addr,addr_ip,sizeof(addr_ip)); //Change the IP address into char *
if(n == -1 || n == 0) {
if(n == -1) {
perror("Error when read data");
} else {
printf("Client %s:%d has closed the connection\n",addr_ip,ntohs(client_addr.sin_port));
}
epoll_ctl(epoll_fd,EPOLL_CTL_DEL,connect_fd,NULL);
close(connect_fd);
continue;
}
memset(buf+n,0,1024-n);
printf("Receive data from %s:%d,%s\n", addr_ip,ntohs(client_addr.sin_port),buf);
}
}
}
}