(1)要求:
(2)代码:以收发图片为例
客户端:
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<sys/stat.h>
int main()
{
int rCnt;
int fd;
int sockfd;
int ret;
struct sockaddr_in saddr = {0};
socklen_t slen;
char rdBuff[4*1024] = {0};
char cmd[20] = {0};
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockfd < 0)
{
perror("socket failed\n");
exit(1);
}
printf("sockfd:%d\n",sockfd);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8090);
saddr.sin_addr.s_addr = inet_addr("192.168.56.133");
slen = sizeof(saddr);
do{
ret = connect(sockfd,(struct sockaddr *)&saddr,slen);
}while(ret != 0);
printf("connect successfully\n");
while(1)
{
printf("enter your request:\n");
scanf("%s",cmd);
fd = open("./data/2.png",O_WRONLY|O_CREAT,0777);
if(fd < 0) continue;
write(sockfd,cmd,16);
while(1)
{
rCnt = read(sockfd,rdBuff,4*1024);
//printf("rCnt = %d\n",rCnt);
write(fd,rdBuff,rCnt);
if(rCnt < 4*1024) break;
}
close(fd);
}
close(sockfd);
return 0;
}
服务端:
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<sys/stat.h>
void cmdParse_Handler(int cfd,const char *pcmd);
int main()
{
int fd;
int sockfd,client_fd;
int cnt;
struct sockaddr_in saddr,caddr;
socklen_t slen,clen;
char rdBuff[128] = {0};
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockfd < 0)
{
perror("socket failed\n");
exit(1);
}
printf("sockfd:%d\n",sockfd);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8090);//设定一个服务器的端口号
saddr.sin_addr.s_addr = htons(INADDR_ANY);
slen = sizeof(saddr);
clen = sizeof(caddr);
bind(sockfd,(struct sockaddr *)&saddr,slen);
listen(sockfd,100);
while(1)
{
printf("listen ...\n");
//accept()拿到客户端的端口和ip地址
client_fd = accept(sockfd,(struct sockaddr *)&caddr,&clen);
printf("connect successfully\n");
printf("client_fd:%d\n",client_fd);
printf("waiting the request...\n");
while(1)
{
cnt = read(client_fd,rdBuff,128);
if(cnt < 0)
{
perror("resd failed\n");
exit(2);
}
else if(cnt == 0)
{
printf("client offline...\n");
close(client_fd);
break;
}
else{
printf("rd:%s\n",rdBuff);
cmdParse_Handler(client_fd,rdBuff);
}
}
}
close(sockfd);
}
void cmdParse_Handler(int cfd,const char *pcmd)
{
int fd;
int rCnt;
char buffer[4*1024] = {0};
if(cfd <0 || pcmd == NULL)
return;
if(strcmp(pcmd,"getText") == 0)
{
write(cfd,"send text now!",20);
}
else if(strcmp(pcmd,"getPhoto") == 0)
{
printf("send photo now!\n");
fd = open("./data/1.png",O_RDONLY);
if(fd < 0) return ;
while(1)
{
rCnt = read(fd,buffer,4*1024);
write(cfd,buffer,rCnt);
if(rCnt < 4*1024) break;
}
close(fd);
}
else if(strcmp(pcmd,"getVideo") == 0)
{
write(cfd,"send video now!",20);
}
else
{
printf("parse error\n");
write(cfd,"cmd error",20);
}
}
(3)运行结果:
(4)分析:
scanf输入数据之后,要手动回车,才能刷新缓冲区。
发送多个文件时,要考虑解决粘包问题。
发送命令优先使用字符串,数字容易引起破坏、不稳定等。不过,一般问题不大。
accept()函数拿到客户端的端口和ip地址。