服务器:socket() --> bind() --> listen() --> accept() --> read/write or recv/send–>close()
客户端:socket() --> connect() --> read/write or recv/send -->close()
测试例子:
1.客户端给服务器发送一个字符串,服务器返回给客户端这个字符串的长度 。
2.实现一个时间服务器,客户端发送time,服务器返回当前时间。
3.如果客户端发送的请求,服务器获取文件内容后,发送给客户端 。
服务器:
/*===============================================* 文件名称:server.c* 创 建 者: xm * 创建日期:2022年08月16日* 描 述:================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
void fun_work1(char *str,int connfd);//例子1
void fun_work2(int connfd);//例子2
int fun_work3(int connfd);//例子3
int main(int argc, char *argv[])
{ int sockfd=socket(PF_INET,SOCK_STREAM,0);if(sockfd<0){perror("socket");return -1;}//端口复用函数,为解决端口号被系统占用的情况(如由强制关闭服务器引起)int on=1;int k=setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));if(k==-1){perror("setsockopt");return -1;}struct sockaddr_in server_addr={0};server_addr.sin_family=AF_INET;server_addr.sin_port=htons(9000);//server_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//能匹配本机所有ip地址server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//也可以用宏,相当于0.0.0.0int len_ser=(int)sizeof(server_addr);if(bind(sockfd,(struct sockaddr*)&server_addr,len_ser)==-1){perror("bind");return -1;}if(listen(sockfd,10)==-1){perror("listen");return -1;}struct sockaddr_in client_addr={0};int len_cli=sizeof(client_addr);while(1)//循环服务器,解决客户端强制关闭导致服务器死循环或者直接退出的情况{ printf("wait n");int connfd=accept(sockfd,(struct sockaddr*)&client_addr,&len_cli);if(connfd<0){perror("accept");return -1;}printf("client ip:%s client port:%dn",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));//收发数据char buf[64]={0};while(1){int m=read(connfd,buf,64);if(m<0){perror("read");return -1;}else if(m==0)//客户端关闭,客户端用ctrl+c强制退出也算关闭{close(connfd);break;}printf(">%sn",buf);int ret;if(strcmp(buf,"time")==0)//例子2{fun_work2(connfd);}else if(strcmp(buf,"")==0)//例子3{ret=fun_work3(connfd);}else{fun_work1(buf,connfd);//例子1}memset(buf,0,64);}}close(sockfd);return 0;
}
void fun_work1(char *buf,int connfd)
{char *str=buf;sprintf(str,"%ld",strlen(str));write(connfd,str,strlen(str));
}
void fun_work2(int connfd)
{char buf[64]={0};time_t mytime;time(&mytime);char *str=ctime(&mytime);strcpy(buf,str);write(connfd,buf,strlen(buf));}
int fun_work3(int connfd)
{int cp_fd=open("./../1.txt",O_RDONLY);if(cp_fd<0){perror("open");return -1;}int m,ret;char buf[64]={0};while((m=read(cp_fd,buf,64))>0){ret=write(connfd,buf,m);if(ret<0){perror("write");return -1;}fputs(buf,stdout);}printf("获取1.txt文件成功n");close(cp_fd);}
客户端:
/*===============================================
* 文件名称:client.c
* 创 建 者: xm
* 创建日期:2022年08月16日
* 描 述:
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
int client_work1(int sockfd);//例子1
int client_work2(int sockfd);//例子2
int client_work3(int sockfd);//例子3
int main(int argc, char *argv[])
{ int sockfd=socket(PF_INET,SOCK_STREAM,0);//创建套接字if(sockfd<0){perror("socket");return -1;}struct sockaddr_in client_addr={0};client_addr.sin_family=AF_INET;client_addr.sin_port=htons(9000);//要连接的服务器的端口号//client_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//能匹配本机所有ip地址client_addr.sin_addr.s_addr=htonl(INADDR_ANY);//也可以用宏,相当于0.0.0.0int len_cli=(int)sizeof(client_addr);if(connect(sockfd,(struct sockaddr*)&client_addr,len_cli)==-1){perror("connect");return -1;}printf("client ip:%s client port:%dn",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));//收发数据char buf[64]={0};while(1){printf("n--------特殊功能关键字--------n");printf("----quit---- 关闭客户端n");printf("----time---- 查看当前时间n");printf("-------- 下载文件测试n");printf("input:n"); fgets(buf,64,stdin);buf[strlen(buf)-1]='