编译方式:
client : gcc -o client client.c tcpfd.c
server: gcc -o server server.c tcpfd.c
可直接无参在自己机器运行,默认127.0.0.1:1029 client.c文件,其他方式参数输入方式见代码
1.client.c
#include "head.h"
#include "tcpfd.h"
int main(int argc, char **argv){
char *servaddr;
int port;
int clientfd;
char msg[MSG_SIZE];
if (argc < 4){
servaddr = (char *)"127.0.0.1";//地址
port = 1029;//端口
strcpy(msg, "client.c");//文件名
}
else{
servaddr = argv[1];
port = atoi(argv[2]);
strcpy(msg, argv[3]);
}
printf("------------Client started------------\n");
printf("Server Info:\n");
printf("Address: %s Port: %d\n", servaddr, port);
if ((clientfd = open_clientfd(servaddr, port)) < 0){
printf("Connect error \n");
exit(1);
}
//transmission
send_msg(clientfd, msg);
rev_file(clientfd, msg);
printf("Connect closed \n");
printf("------------Client closed------------\n");
exit(0);
}
2.server.c
#include "head.h"
#include "tcpfd.h"
/*
编译指令:
cc main.c -o server.o -lpthread
*/
void *thread_l1(void *vargp);
int main(int argc, char **argv)
{
int listenfd;
int port;
struct sockaddr_in clientaddr;
int clientlen;
int *connectedfdp;
struct hostent *hp;
char *hpaddr;
//thread
pthread_t tid_l1;
if (argc < 2){
port = 1029;
}
else{
port = atoi(argv[1]);
}
printf("------------Server started------------\n");
printf("Server Info: \n");
printf("Port: %d\n", port);
if ((listenfd = open_listenfd(port)) < 0){
printf("server create error\n");
exit(1);
}
while(1){
clientlen = sizeof(struct sockaddr_in);
connectedfdp = (int *)malloc(sizeof(int));
*connectedfdp = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&clientlen);
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
hpaddr = inet_ntoa(clientaddr.sin_addr);
printf("Client connected from %s ==> %s\n", hp->h_name, hpaddr);
//thread & semaphore
pthread_create(&tid_l1, NULL, thread_l1, connectedfdp);
}
printf("------------Server closed------------\n");
exit(0);
}
void *thread_l1(void *vargp)
{
static int pcnt = 0;
int connectfd_tl1 = *((int *)vargp);
pthread_detach(pthread_self());
free(vargp);
char msg[MSG_SIZE];
char *filename = recv_msg(connectfd_tl1, msg);
printf("Thread %d:\n", pcnt);
pcnt++;
send_file(connectfd_tl1, filename);
printf("\n");
close(connectfd_tl1);
return NULL;
}
3.tcpfd.c
#include "head.h"
#include "tcpfd.h"
int open_clientfd(char *servname, int port)
{
int clientfd;
struct hostent *hp;
struct sockaddr_in servaddr;
struct in_addr addr;
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("open_clientfd: socket error");
return -1;
}
if (inet_aton(servname, &addr) != 0)
hp = gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET);
else
hp = gethostbyname(servname);
bzero((char *)&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0],
(char *)&servaddr.sin_addr.s_addr, hp->h_length);
servaddr.sin_port = htons(port);
if (connect(clientfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
printf("open_clientfd: connect error\n");
return -1;
}
printf("Connect created.\n");
return clientfd;
}
void rev_file(int fd, char *filename)
{
char buffer[BUFFER_SIZE];
FILE *fp = fopen(filename, "w");
if (fp == NULL)
{
printf("File: %s Can Not Open To Write!\n", filename);
exit(1);
}
// 从服务器端接收数据到buffer中
bzero(buffer, sizeof(buffer));
int length = 0;
while((length = recv(fd, buffer, BUFFER_SIZE, 0)) > 0)
{
int write_length = fwrite(buffer, sizeof(char), length, fp);
if (write_length < length)
{
printf("File: %s Write Failed!\n", filename);
break;
}
bzero(buffer, BUFFER_SIZE);
}
if (length < 0)
{
printf("Recieve Data From Server Failed!\n");
}
printf("Recieve File: %s From Server Finished!\n", filename);
// 传输完毕,关闭socket
fclose(fp);
close(fd);
}
void send_msg(int fd, char *msg)
{
if (send(fd, msg, strlen(msg), 0) < 0)
{
printf("send_msg: %s Failed!\n", msg);
return;
}
printf("MSG Sended: %s\n", msg);
}
int open_listenfd(int port)
{
int listenfd;
int optval = 1;
struct sockaddr_in servaddr;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("open_listenfd: listenfd socket error\n");
return -1;
}
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(int)) < 0){
printf("open_listenfd: setsockopt error\n");
return -1;
}
bzero((char *)&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons((unsigned int)port);
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))<0){
printf("open_listenfd: bind error\n");
return -1;
}
if(listen(listenfd, 16)<0){
printf("open_listenfd: listen error\n");
return -1;
}
printf("------------Server Created------------\n");
printf("\n");
return listenfd;
}
void send_file(int fd, char *filename)
{
char buffer[BUFFER_SIZE];
printf("send File: %s \n", filename);
FILE *fp = fopen(filename, "r");
if (fp == NULL)
{
printf("File: %s Not Found!\n", filename);
}
else
{
bzero(buffer, BUFFER_SIZE);
int file_block_length = 0;
while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
//printf("file_block_length = %d\n", file_block_length);
// 发送buffer中的字符串到fd,实际上就是发送给客户端
if (send(fd, buffer, file_block_length, 0) < 0)
{
printf("Send File: %s Failed!\n", filename);
break;
}
bzero(buffer, sizeof(buffer));
}
fclose(fp);
printf("File: %s Transfer Finished!\n", filename);
}
}
char* recv_msg(int fd, char msg[])
{
int length;
bzero(msg, MSG_SIZE);
if ((length = recv(fd, msg, MSG_SIZE, 0)) < 0)
{
printf("recv_msg: %s Failed!\n", msg);
}
printf("MSG Recveived: %s \n", msg);
return msg;
}
4.tcpfd.h
#define BUFFER_SIZE 1024
#define MSG_SIZE 128
int open_clientfd(char *servname, int port);
void rev_file(int fd, char *filename);
void send_msg(int fd, char *msg);
int open_listenfd(int port);
void send_file(int fd, char *filename);
char* recv_msg(int fd, char msg[]);
5.head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif