在客户端输入要上传的照片,服务器就会将图片上传到serpic文件夹中
在服务器输入要发送的照片,服务器就会将图片发送给客户端的mypic文件夹中
有两张图片保存在当前路径下1.png 2.png
pic_client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
//图片最大4KB 只能是png,jpg需要改一下代码
#define PSIZE 4*1024
void *send_msg(void *arg);
void *recv_msg(void *arg);
int main(int argc, char *argv[])
{
if(argc != 3){
printf("%s ip port.\n", argv[0]);
return -1;
}
//参数:ip协议 TCP 0
//应用层到底层的通道
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sfd){
perror("socket");
return -1;
}
//设置ip port
struct sockaddr_in sddr, cddr;
memset(&sddr, 0, sizeof(sddr));
bzero(&cddr, sizeof(struct sockaddr_in));
sddr.sin_family = AF_INET;
sddr.sin_port = htons(atoi(argv[2]));
//设置服务器为自己主机的任意ip == INADDR_ANY
sddr.sin_addr.s_addr = inet_addr(argv[1]);
int confd = connect(sfd,(void *)&sddr,sizeof(sddr));
if(-1 == confd)
{
perror("connect");
return -1;
}
printf("connect success.\n");
//创建两个子线程
pthread_t sid, rid;
//发送消息线程
sid = pthread_create(&sid,NULL, send_msg, &sfd);
if(sid == -1)
{
perror("pthread_create1");
return -1;
}
//接收消息线程
rid = pthread_create(&rid,NULL, recv_msg, &sfd);
if(rid == -1)
{
perror("pthread_create1");
return -1;
}
while(1){
sleep(1);
}
return 0;
}
void *send_msg(void *arg){
int fd = *((int *)arg);
char buf[PSIZE] = {0};
char pic_path[20]={0};
while(1){
scanf("%s", pic_path);
int pic_fd = open(pic_path,O_RDWR);
if(pic_fd < 0)
{
perror("open");
exit(0);
}
int n = read(pic_fd,buf,PSIZE);
write(fd, buf, n);
if(strncmp(buf,"quit",4)==0)
exit(0);
printf("上传成功!\n");
}
}
void *recv_msg(void *arg){
int fd = *((int *)arg);
char buf[PSIZE] = {0};
int clifd = open("mypic/my_pic.png", O_RDWR|O_CREAT|O_TRUNC, 0666);
while(1){
int n = read(fd, buf, PSIZE);
if(n==0) exit(0);
write(clifd, buf, n);
printf("服务器向你发送了一张图片.\n");
}
}
pic_server.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PSIZE 4*1024
void *send_msg(void *arg);
void *recv_msg(void *arg);
int main(int argc, char *argv[])
{
//参数:ip协议 TCP 0
//应用层到底层的通道
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sfd){
perror("socket");
return -1;
}
//设置ip port
struct sockaddr_in sddr, cddr;
memset(&sddr, 0, sizeof(sddr));
bzero(&cddr, sizeof(struct sockaddr_in));
sddr.sin_family = AF_INET;
sddr.sin_port = htons(8008);
//设置服务器为自己主机的任意ip == INADDR_ANY
sddr.sin_addr.s_addr = inet_addr("0.0.0.0");
/*
*bind:将ip,port 和 套接字绑定
*参数:sockfd (struct sockaddr *) saddr大小
*返回值 0成功 -1失败
* */
if(-1 == bind(sfd,(void *)&sddr,sizeof(sddr)))
{
perror("bind");
return -1;
}
//监听
/*
*listen:监听套接字有无连接进来
*sockfd: 目标套接字的文件描述符
*10: 监听队列的长度
*return : 0 success -1 failed
* */
if(-1 == listen(sfd, 10))
{
perror("listen");
return -1;
}
puts("listen---------");
/*
*accept: 和客户端建立新的连接
*参数:sockfd
*cddr: 存储连接进来的客户端信息ip port可以是NULL
*len: sizeof(cddr)
*return: 表示新的连接
* */
socklen_t len = sizeof(cddr);
int nfd = accept(sfd,(void *)&cddr,&len);
if(-1 == nfd){
perror("accept");
return -1;
}
//解析客户端ip 和 port 需要用到inet_ntoa() ntohs()转换
printf("IP:%s PORT:%d connected.\n",inet_ntoa(cddr.sin_addr),
ntohs(cddr.sin_port));
//创建两个子线程
pthread_t sid, rid;
//发送消息线程
sid = pthread_create(&sid,NULL, send_msg, &nfd);
if(sid == -1)
{
perror("pthread_create1");
return -1;
}
//接收消息线程
rid = pthread_create(&rid,NULL, recv_msg, &nfd);
if(rid == -1)
{
perror("pthread_create1");
return -1;
}
while(1){
sleep(1);
}
return 0;
}
void *send_msg(void *arg){
//可以向客户端发送一张图片
int fd =*(int *)arg;
char buf[PSIZE] = {0};
char pic_path[20] = {0};
while(1){
scanf("%s", pic_path);
int picfd = open(pic_path,O_RDWR);
if(picfd < 0)
{
perror("picfd");
exit(0);
}
int n = read(picfd, buf, PSIZE);
if(strncmp(buf,"quit",4)==0)
exit(0);
write(fd, buf, n);
}
}
void *recv_msg(void *arg){
//接收客户端发过来的图片 保存为serpic.png
int fd = *((int *)arg);
char buf[PSIZE] = {0};
int picfd = open("serpic/serpic.png",O_RDWR|O_CREAT|O_TRUNC, 0666);
while(1){
sleep(1);
int n = read(fd, buf, PSIZE);
if(n==0)
exit(0);
write(picfd, buf, n);
printf("已将图片保存为serpic.png.\n");
}
}
编译
gcc pic_client.c -o pic_cli -lpthread
gcc pic_server.c -o pic_ser -lpthread
运行结果
打开两个终端
第一个终端输入:
./pic_ser
第二个终端输入:
./pic_cli 127.0.0.1 8008
如果出现bind:地址已被占用 关闭所有终端重新再来,实在不行就挂起虚拟机再开