一共两个部分:服务器、客户端
头文件:
#ifndef __MAKEU_NET_H__
#define __MAKEU_NET_H__
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SERV_PORT 5002 //端口
#define SERVER_IP_ADDR "192.168.1.10"
#define BACKLOG 5
#define QUIT_STR "quit"
#define SERV_RESP_STR "SERVER:"
#endif
服务器:
首先介绍流程
1、socket返回一个fd
2、填写struct sockaddr_in sin 信息
3、bind绑定信息
4、listen 将fd设置为监听模式
5、accept等待客户端连接
6、用frok创建一个线程去处理这个客户端
#include "net.h"
#include "string.h"
#include "pthread.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
void client_handle(void *arg);
void sig_chil_handle(int signo)
{
if(SIGCHLD == signo)
{
waitpid(-1,NULL,WNOHANG);
}
}
int main(void)
{
int fd = -1;
struct sockaddr_in sin;
fd = socket(AF_INET,SOCK_STREAM,0);
int b_reuse = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));
//填充sin数据
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_PORT);
sin.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR);
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0 )
{
perror("bind");
exit(1);
}
if(listen(fd,BACKLOG) != 0)
{
perror("listen");
exit(1);
}
printf("server starting...OK!\n");
int newfd;
char buf[BUFSIZ];
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
while (1)
{
pid_t pid = -1;
if((newfd = accept(fd,(struct sockaddr *)&cin,&addrlen)) < 0)
{
perror("accept");
break;
}
if((pid = fork()) < 0)
{
perror("fork");
break;
}
if(pid == 0)//子进程
{
close(fd);
if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,buf,sizeof(cin)))
{
perror("inet_ntop");
exit(1);
}
printf("hello\n");
client_handle((void *)&newfd);
return 0;
}
else
{
close(newfd);
}
}
}
void client_handle(void *arg)
{
int ret = -1;
int newfd = *(int *)arg;
char buf[BUFSIZ];
char resp_buf[BUFSIZ + 10];
printf("child handling proccess : newfd = %d\n",newfd);
while (1)
{
bzero(buf,BUFSIZ);
bzero(resp_buf,BUFSIZ + 10);
do
{
ret = read(newfd,buf,BUFSIZ);
}while(ret < 0 && EINTR == errno);
if(ret < 0)
{
perror("read");
exit(1);
}
if(ret == 0)
{
printf("客户端已下线");
break;
}
bzero(resp_buf,BUFSIZ+10);
strncpy(resp_buf,SERV_RESP_STR,strlen(SERV_RESP_STR));
strcat(resp_buf,buf);
do
{
ret = write(newfd,resp_buf,strlen(resp_buf));
}while(ret < 0 && EINTR == errno);
printf("client (fd = %d) :%s\n",newfd,buf);
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("Client(fd=%d) is exiting!\n",newfd);
break;
}
}
close(newfd);
}
客户端:
1、socket
2、填cin信息
3、connect服务器
4、用select监控键盘输入和服务器数据
#include "net.h"
int main(int argc,char **argv)
{
struct sockaddr_in cli;
bzero(&cli,sizeof(cli));
int fd = socket(AF_INET,SOCK_STREAM,0);
cli.sin_family = AF_INET;
cli.sin_port = htons(SERV_PORT);//端口转换
cli.sin_addr.s_addr = inet_addr(argv[1]);//要连接的地址
if(connect(fd,(struct sockaddr *)&cli,sizeof(cli)) < 0)
{
perror("connect");
exit(1);
}//连接
printf("cli connect succeed...OK\n");
int maxfd = -1;
struct timeval tout;
fd_set rset;
char buf[BUFSIZ];
int ret = -1;
int recordfd = -1;
recordfd = open("record.txt",O_RDWR);
while (1)
{
//
FD_ZERO(&rset);
FD_SET(0,&rset);
FD_SET(fd,&rset);
maxfd = fd;
tout.tv_sec = 5;
tout.tv_usec = 0;
select(maxfd + 1,&rset,NULL,NULL,&tout);
//判断哪个fd进来数据
if(FD_ISSET(0,&rset))
{
bzero(buf,BUFSIZ);
do{
ret = read(0,buf,BUFSIZ -1);
}while(ret < 0 && EINTR == errno);
if(ret < 0)
{
perror("read");
continue;
}
if(!ret)
{
continue;
}
if(write(fd , buf, strlen(buf)) < 0)
{
perror("write() to socket");
continue;
}
if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))//退出
{
printf("Client is exiting!\n");
break;
}
}
if(FD_ISSET(fd,&rset))
{
bzero(buf,BUFSIZ);
do
{
ret = read(fd,buf,BUFSIZ -1);
} while (ret < 0 && EINTR == errno);
if(ret < 0)
{
perror("read");
continue;
}
if(!ret)//服务器已关闭
{
break;
}
printf("server said : %s\n",buf);
if(write(recordfd,buf,strlen(buf)) < 0)
{
perror("write to record\n");
}
}
if(strlen(buf) > strlen(SERV_RESP_STR) && !strncasecmp(buf+strlen(SERV_RESP_STR),QUIT_STR,strlen(QUIT_STR)))
{
printf("client quit!\n");
break;
}
}
close(fd);
return 0;
}