#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#define MAXLINE 1024
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
#define MAX(a,b) a>b?a:b
#if 0
void str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE], recvline[MAXLINE];
while(fgets(sendline,MAXLINE,fp)){
write(sockfd, sendline, strlen(sendline));
if(read(sockfd, recvline, MAXLINE) == 0){
ERR_EXIT("str_cli:server terminated prematurely");
}
fputs(recvline, stdout);
}
}
#endif
//use select
void str_cli(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof = 0;
FD_ZERO(&rset);
for ( ; ; ){
//可以处理client半关闭状态
if ( 0 == stdineof){
//fileno函数,把标准的I/O文件指针转化为对应的描述符
//stdin & stdout 通过fileno转化为对应的fd
FD_SET(fileno(fp), &rset);
}
FD_SET(sockfd, &rset);
maxfdp1 = MAX(fileno(fp), sockfd)+1;
printf("fileno(fp):%d, sockfd:%d, maxfdp1=%d\n", fileno(fp),sockfd,maxfdp1);
select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset)){
if ((n = read(sockfd, buf, MAXLINE)) == 0){
//server端close socket,发送FIN给client
printf("client & server disconnect\n");
if (stdineof == 1){
return;
}else{
ERR_EXIT("str_cli: server terminated prematurely");
}
}
//显示到标准输出
write(fileno(stdout), buf, n);
}
if (FD_ISSET(fileno(fp), &rset)){
if ((n = read(fileno(fp), buf, MAXLINE)) == 0)
{
printf("client close and send fin to server\n");
stdineof = 1;
//client 发送FIN给server,关闭连接的写这一半.client只能收数据
shutdown(sockfd, SHUT_WR);//send FIN to server
//通知内核清除监听标准的I/O操作
FD_CLR(fileno(fp), &rset);
continue;
}
//发server端发送数据
write(sockfd, buf, n);
}
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
//创建sockfd
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
ERR_EXIT("socket error");
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(49160);
//servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if((inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr))<0)
ERR_EXIT("inet_pton error");
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
ERR_EXIT("connect error");
}
//SET SO_LINGER
//struct linger so_linger;
//so_linger.l_onoff = 1;
//so_linger.l_linger = 0;
//setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&so_linger, sizeof(so_linger));
str_cli(stdin, sockfd);
ERR_EXIT(0);
return 0;
}
tcp 回射客户端,select 检查socket的状态信息
最新推荐文章于 2024-03-05 07:51:58 发布