文章目录
服务端
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include<ctype.h>
#include<stdlib.h>
#include<signal.h>
#include<wait.h>
void do_sig(int num){
while(waitpid(0,NULL,WNOHANG)>0);
}
int main(void){
//lfd:socket返回的文件描述符,用lfd监听并接受客户端连接
//cfd:客户端链接上来返回的cfd,用cfd和客户端通信
int lfd,cfd,len,i;
char buf[1024];//缓冲区
//serv_addr服务器地址
//client_addr客户端地址
struct sockaddr_in serv_addr,client_addr;
socklen_t client_len;
//进程id
pid_t pid;
//杀死僵尸进程
struct sigaction act;
act.sa_handler = do_sig;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD,&act,NULL);
//socket创建服务器返回lfd文件描述符
lfd = socket(AF_INET,SOCK_STREAM,0);
bzero(&serv_addr,sizeof(serv_addr));
//ipv4
serv_addr.sin_family = AF_INET;
//端口 本地字节序转网络字节序 host to net short 大小端存储问题
serv_addr.sin_port = htons(9999);
//ip host to net long
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind
bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
//监听是否有客户连接
listen(lfd,128);
printf("wait for connect...\n");
while(1){
client_len = sizeof(client_addr);//客户端地址长度
//连接成功返回cfd,用cfd和客户通信
cfd = accept(lfd,(struct sockaddr*)&client_addr,&client_len);
printf("connect success...\n");
//创建进程
pid = fork();
if(pid==0){//child
close(lfd);//子进程用不到lfd,因为lfd是父进程用来接收客户端连接的
while(1){
len = read(cfd,buf,sizeof(buf));
printf("receive: %s\n",buf);
if(len<=0)break;
for(i=0;i<len;++i)
buf[i] = toupper(buf[i]);
write(cfd,buf,len);
}
close(cfd);//客户端断开连接
return 0;
}else if(pid>0) {//parent
close(cfd);//父亲进程用不到cfd,因为cfd是子进程用来和客户端通信的
}else{
perror("fork fail...");
exit(1);
}
}
}
客户端
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#define DEST_PORT 9999//目标地址端口号
#define DEST_IP "127.32.255.2"/*目标地址IP,这里设为本机,不一定非得是127.0.0.1,只要127开头并且不是127.0.0.0和127.255.255.255即可*/
#define MAX_DATA 100//接收到的数据最大程度
int main(){
int sockfd;
struct sockaddr_in dest_addr;
char buf[MAX_DATA];
sockfd=socket(AF_INET,SOCK_STREAM,0);
dest_addr.sin_family=AF_INET;
dest_addr.sin_port=htons(DEST_PORT);
dest_addr.sin_addr.s_addr=inet_addr(DEST_IP);
bzero(&(dest_addr.sin_zero),8);
connect(sockfd,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr));
printf("connect success");
while(1){
char send_buf[512] = "";
scanf("%s",&send_buf);
write(sockfd,send_buf,sizeof(send_buf));
read(sockfd,send_buf,sizeof(send_buf));
printf("client receive:%s\n",send_buf);
}
return 0;
}
centos执行
gcc -o server.out server.c
gcc -o client.out client.c
得到执行文件server.out,client.out
用xshell 对一个虚拟机开两个item窗口,一个执行./server.out ,另一个执行./client.out
可以用ps -aux 查看进程状态,看看有没有僵尸进程,本例中已经处理过僵尸进程