开发环境
Red Hat Enterprise Linux Server release 7.0 (Maipo)
Client相关代码:
//client.c
#include "myhead.h"
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2) {
printf("Usages :tcpcli1 <IPaddres>\n");
return -1;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("socket error:%s\n", strerror(errno));
return -1;
}
memset(&servaddr, 0x00, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
printf("inet_pton error:%s\n", strerror(errno));
return -1;
}
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
printf("connect error:%s\n", strerror(errno));
return -1;
}
str_cli(stdin, sockfd);
exit(0);
}
//myhead.h
/*================================================================
* Copyright (C) 2019 Sangfor Ltd. All rights reserved.
*
* 文件名称:myhead.h
* 创 建 者:gaojie
* 创建日期:2019年04月08日
* 描 述:定义网络编程常用的头文件,宏。
*
================================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#define max(a,b) ((a) > (b) ? (a) : (b))
#define SERV_PORT 9877
#define MAXLINE 4096
void str_cli(FILE *fp, int sockfd) ;//回射 select shutdown mul
//str_cli.c
/*================================================================
* Copyright (C) 2019 Sangfor Ltd. All rights reserved.
*
* 文件名称:str_cli.c
* 创 建 者:gaojie
* 创建日期:2019年04月08日
* 描 述:
*
================================================================*/
#include "myhead.h"
void str_cli(FILE *fp, int sockfd) {
char sendline[MAXLINE], recvline[MAXLINE];
fd_set rset;
int maxfdpl,stdineof;
int n;
stdineof = 0;
FD_ZERO(&rset);
//while (fgets(sendline, MAXLINE, fp) != NULL) {
for(;;){
if(stdineof == 0)
FD_SET(fileno(fp),&rset);
FD_SET(sockfd,&rset);
maxfdpl = max(fileno(fp),sockfd) + 1;
n = select(maxfdpl,&rset,NULL,NULL,NULL);
if(n == -1)
{
printf("select error:%s",strerror(errno));
return ;
}
if(FD_ISSET(sockfd,&rset))
{
if((n = read(sockfd,recvline,MAXLINE)) == 0)
{
if(stdineof == 1)
return;
else
{
printf("str_cli:server terminated prematurely!\n");
exit(0) ;
}
}
recvline[n] = '\0';
printf("%s\n",recvline);
}
if(FD_ISSET(fileno(fp),&rset))
{
if(fgets(sendline, MAXLINE, fp) == NULL)
{
stdineof = 1;
shutdown(sockfd,SHUT_WR);
FD_CLR(fileno(fp),&rset);
continue;
}
if(write(sockfd,sendline,strlen(sendline)) < 0)
{
printf("write error:%s\n",strerror(errno));
}
}
memset(sendline, 0x00, MAXLINE);
memset(recvline, 0x00, MAXLINE);
}
}
Server相关代码:
//server.c
#include "myhead.h"
typedef void sigfunc(int);
sigfunc* signal(int signo,sigfunc *func)
{
struct sigaction act,oact;
act.sa_handler=func;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
if(signo==SIGALRM)
{
#ifdef SA_INTERRUPT
act.sa_flags|=SA_INTERRUPT;
#endif
}else{
#ifdef SA_RESTART
//act.sa_flags|=SA_RESTART;
#endif
}
if(sigaction(signo,&act,&oact)<0)
return(SIG_ERR);
return(oact.sa_handler);
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
while(( pid = waitpid(-1,&stat,WNOHANG))>0)
printf("child %d terminated\n",pid);
return;
}
void ChangeBuff(char *writebuff,const char *buff)
{
if(writebuff==NULL||buff==NULL) return;
int i=0;
for(i=0;buff[i]!='\0';i++)
{
if(isupper(buff[i]))
writebuff[i]=tolower(buff[i]);
else if(islower(buff[i]))
writebuff[i]=toupper(buff[i]);
else
writebuff[i]=buff[i];
}
}
void MulToInt(const char *buff,char *writebuff)
{
if(writebuff==NULL||buff==NULL)return;
int element1=0,element2=0;
while(!isdigit(*buff)) buff++;
while(*buff!=' ' && isdigit(*buff))
{
element1=element1*10 + (*buff - '0');
buff++;
}
buff++;
while(*buff!='\0' && isdigit(*buff))
{
element2=element2*10 + (*buff - '0');
buff++;
}
int res = element1 * element2;
char tmpstr[256]={0};
sprintf(tmpstr,"%d",res);
int i = 0;
while(tmpstr[i]!='\0')
{
*writebuff = tmpstr[i++];
writebuff++;
}
}
void str_echo(int sockfd) {
ssize_t n;
char buf[MAXLINE];
char writebuff[MAXLINE];
for(;;) {
if ((n = read(sockfd, buf, MAXLINE)) == 0)
return;
MulToInt(buf,writebuff);
if (write(sockfd, writebuff, n) < 0) {
printf("write error:%s\n", strerror(errno));
}
memset(buf, 0x00, MAXLINE);
if (n < 0 && errno != EINTR) {
printf("str_echo: read error:%s\n", strerror(errno));
}
}
}
int main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("socket error:%s\n", strerror(errno));
return -1;
}
memset(&servaddr, 0x00, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
printf("bind error:%s\n", strerror(errno));
return -1;
}
if (listen(listenfd, LISTENQ) < 0) {
printf("listen error:%s\n", strerror(errno));
return -1;
}
signal(SIGCHLD,sig_chld);
for(;;) {
clilen = sizeof(cliaddr);
if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen)) < 0) {
if(errno==EINTR)
{
printf("Interrupted system call but continue\n");
continue;
}
else
{
printf("acctop error!\n:%s",strerror(errno));
return 0;
}
}
if ((childpid = fork()) == 0) {
if (close(listenfd) < 0) {
printf("close listenfd error:%s\n", strerror(errno));
}
str_echo(connfd);
exit(0);
}
if (close(connfd) < 0) {
printf("close connfd error:%s\n", strerror(errno));
}
}
}
//myhead.h
/*================================================================
* Copyright (C) 2019 Sangfor Ltd. All rights reserved.
*
* 文件名称:myhead.h
* 创 建 者:gaojie
* 创建日期:2019年04月08日
* 描 述:定义网络编程常用的头文件,宏。
*
================================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <netinet/in.h>
#define LISTENQ 5
#define max(a,b) ((a) > (b) ? (a) : (b))
#define SERV_PORT 9877
#define MAXLINE 4096
<附加功能>:
客户端可以监测到服务器的断开(socket),服务器也可以监测到客户端的断开(waitpid)
测试结果:
客户端: