selectServerInTCPIPbook.c
的内容如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#define BUF_SIZE 100
void error_handling(char *buf);
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
struct sockaddr_in serv_adr, clnt_adr;
struct timeval timeout;
fd_set reads, cpy_reads;
socklen_t adr_sz;
int fd_max, str_len, fd_num, i;
char buf[BUF_SIZE];
if(argc!=2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
if(listen(serv_sock, 5)==-1)
error_handling("listen() error");
FD_ZERO(&reads);
FD_SET(serv_sock, &reads);
FD_SET(0, &reads);
fd_max=serv_sock;
char send_line[BUF_SIZE];
while(1)
{
cpy_reads=reads;
timeout.tv_sec=5;
timeout.tv_usec=5000;
if((fd_num=select(fd_max+1, &cpy_reads, 0, 0, &timeout))==-1)
break;
if(fd_num==0)
continue;
if (FD_ISSET(STDIN_FILENO, &cpy_reads)) {
FD_CLR(0, &cpy_reads);
if (fgets(send_line, BUF_SIZE, stdin) != NULL) {
int i = strlen(send_line);
if (send_line[i - 1] == '\n') {
send_line[i - 1] = 0;
}
printf("input: %s\n", send_line);
}
}
for(i=1; i<fd_max+1; i++)
{
if(FD_ISSET(i, &cpy_reads))
{
if(i==serv_sock)
{
adr_sz=sizeof(clnt_adr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
FD_SET(clnt_sock, &reads);
if(fd_max<clnt_sock)
fd_max=clnt_sock;
printf("connected client: %d \n", clnt_sock);
}
else
{
str_len=read(i, buf, BUF_SIZE);
if(str_len==0)
{
FD_CLR(i, &reads);
close(i);
printf("closed client: %d \n", i);
}
else
{
write(1, "message from clien:", 19);
write(1, buf, str_len);
write(1,"\n",1);
write(i, "message from server:", 20);
write(i, buf, str_len);
}
}
}
}
}
close(serv_sock);
return 0;
}
void error_handling(char *buf)
{
fputs(buf, stderr);
fputc('\n', stderr);
exit(1);
}
gcc selectServerInTCPIPbook.c -o selectServerInTCPIPbook
进行编译,然后./selectServerInTCPIPbook 8080
端口上监听。
selectClient.c
里边的内容:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define MAXLINE 1024
int main(int argc, char **argv) {
if (argc != 3) {
printf("usage: select01 <IPaddress> or <Port>");
}
int socket_fd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
socklen_t server_len = sizeof(server_addr);
int connect_rt = connect(socket_fd,(struct sockaddr *)&server_addr,server_len);
if(connect_rt<0){
printf("connect failed");
exit(0);
}
char recv_line[MAXLINE], send_line[MAXLINE];
int n;
fd_set readmask;
fd_set allreads;
FD_ZERO(&allreads);
FD_SET(0, &allreads);
FD_SET(socket_fd, &allreads);
for (;;) {
readmask = allreads;
int rc = select(socket_fd + 1, &readmask, NULL, NULL, NULL);
if (rc <= 0) {
printf("select failed\n");
exit(0);
}
if (FD_ISSET(socket_fd, &readmask)) {
n = read(socket_fd, recv_line, MAXLINE);
if (n < 0) {
printf("read error\n");
exit(0);
} else if (n == 0) {
printf("server terminated\n");
exit(0);
}
recv_line[n] = 0;
fputs(recv_line, stdout);
fputs("\n", stdout);
}
if (FD_ISSET(STDIN_FILENO, &readmask)) {
// FD_CLR(0, &allreads); //去掉注册到操作系统里边标准输出的内容
if (fgets(send_line, MAXLINE, stdin) != NULL) {
int i = strlen(send_line);
if (send_line[i - 1] == '\n') {
send_line[i - 1] = 0;
}
printf("now sending %s\n", send_line);
size_t rt = write(socket_fd, send_line, strlen(send_line));
if (rt < 0) {
printf("write failed\n");
exit(0);
}
printf("send bytes: %zu \n", rt);
}
}
}
}
再打开一个终端,gcc selectClient.c -o selectClient
进行编译,然后使用./selectClient 127.0.0.1 8080
连接到自己本机上8080
端口。
之后再客户端上输入good
之后,可以看到客户端收到的message from server:good
这条信息,而服务器也收到了good
的字符串。
为了验证服务器的select
多路复用,使用键盘在服务器这里输入test
字符串,可以看到服务器输出了input: test
而客户端没有任何输出。
此文章为11月Day 13学习笔记,内容来源于极客时间《网络编程实战》。