1、多线程并发服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>#define ERRLOG(msg) do{\
printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);\
perror(msg);\
}while(0)#define N 128
typedef struct _MSG{
int acceptfd;
struct sockaddr_in clientaddr;
}msg_t;void *deal_read_write(void *arg)
{
msg_t msg = *(msg_t *)arg;
printf("客户端[%s:%d]连接到服务器..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
int nbytes = 0;
char buff[N] = {0};
while(1)
{
memset(buff, 0, N);
if(-1 == (nbytes = recv(msg.acceptfd, buff, N, 0)))
{
perror("recv");
break;
}
else if(!nbytes)
{
printf("客户端[%s:%d]断开了连接..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
break;
}
if(!strncmp(buff, "quit", 4))
{
printf("客户端[%s:%d]退出了..\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
break;
}
printf("客户端[%s:%d]发来数据[%s]\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port), buff);
strcat(buff, "-->\n");
if(-1 == send(msg.acceptfd, buff, N, 0))
{
perror("send");
break;
}
}
close(msg.acceptfd);
pthread_exit(NULL);
}int main(int argc, const char *argv[])
{
if(3 != argc)
{
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(-1);
}int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
ERRLOG("socket");
return -1;
}struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));socklen_t serveraddr_len = sizeof(serveraddr);
if(-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
{
ERRLOG("bind");
return -1;
}if(-1 == listen(sockfd, 5))
{
ERRLOG("listen");
return -1;
}struct sockaddr_in clientaddr;
memset(&clientaddr, 0, sizeof(clientaddr));
socklen_t clientaddr_len = sizeof(clientaddr);int acceptfd = 0;
pthread_t tid = 0;
msg_t msg;
int err_code = 0;while(1)
{
if(-1 == (acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len)))
{
ERRLOG("accept");
return -1;
}
msg.acceptfd = acceptfd;
msg.clientaddr = clientaddr;
if(0 != (err_code = pthread_create(&tid, NULL, deal_read_write, &msg)))
{
printf("pthread_create error %s\n", strerror(err_code));
return -1;
}
if(0 != (err_code = pthread_detach(tid)))
{
printf("pthread_detach error %s\n", strerror(err_code));
return -1;
}
}close(sockfd);
return 0;
}
2、多进程并发服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>#define ERRLOG(msg) do{\
printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);\
perror(msg);\
}while(0)#define N 128
void sig_function()
{
wait(NULL);
}int main(int argc, const char *argv[])
{
if(3 != argc)
{
printf("Usage : %s <IP> <port>\n", argv[0]);
return -1;
}int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
ERRLOG("socket");
return -1;
}struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));socklen_t serveraddr_len = sizeof(serveraddr);
if(bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len) < 0)
{
ERRLOG("bind");
return -1;
}if(listen(sockfd, 5) < 0)
{
ERRLOG("listen");
return -1;
}signal(SIGUSR1, sig_function);
struct sockaddr_in clientaddr;
memset(&clientaddr, 0, sizeof(clientaddr));
socklen_t clientaddr_len = sizeof(clientaddr);int acceptfd = 0;
pid_t pid = 0;while(1)
{
if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len)) < 0)
{
ERRLOG("accept");
return -1;
}if((pid = fork()) < 0)
{
ERRLOG("fork");
return -1;
}
else if(!pid)
{
printf("客户端[%s:%d]连接到服务器..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
int nbytes = 0;
char buff[N] = {0};
while(1)
{
memset(buff, 0, N);
if((nbytes = recv(acceptfd, buff, N, 0)) < 0)
{
ERRLOG("recv");
return -1;
}
else if(!nbytes)
{
printf("客户端[%s:%d]断开了连接..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
break;
}
if(!strncmp(buff, "quit", 4))
{
printf("客户端[%s:%d]退出了..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
break;
}
printf("客户端[%s:%d]发来数据[%s]\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buff);
strcat(buff, "--hqyj");
if(send(acceptfd, buff, N, 0) < 0)
{
ERRLOG("send");
return -1;
}
}
close(acceptfd);
kill(getppid(), SIGUSR1);
return 0;
}
else if(pid > 0)
{
close(acceptfd);
}
}close(sockfd);
return 0;
}
3、fttp下载上传
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>#define ERR_MSG(msg) do{\
fprintf(stderr, "__%d__:", __LINE__);\
perror(msg);\
}while(0)int do_download(int sfd, struct sockaddr_in sin);
int do_upload(int sfd, struct sockaddr_in sin);int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("please--> %s <IP> <PORT>\n", argv[0]);
return -1;
}int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);char c = 0;
int flag = 1;
while(1)
{
system("clear");
printf("**********************\n");
printf("*******1.下载*********\n");
printf("*******2.上传*********\n");
printf("*******3.退出*********\n");
printf("**********************\n");
printf("请输入>>>");c = getchar();
while(getchar()!=10);switch(c)
{
case '1':
do_download(sfd, sin);
break;
case '2':
do_upload(sfd, sin);
break;
case '3':
flag = 0;
break;
default:
printf("输入错误,请重新输入\n");
}if(!flag)
{
break;
}
printf("输入任意字符清屏>>>");
while(getchar() !=10);
}
close(sfd);
return 0;
}int do_download(int sfd, struct sockaddr_in sin)
{
char filename[20] = "";
char buf[516] = "";bzero(buf, sizeof(buf));
printf("请输入要下载的文件名>>>");
fgets(filename, sizeof(filename), stdin);
filename[strlen(filename)-1] = 0;int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);
if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}int fd = -1, flag = 0;
socklen_t addrlen = sizeof(sin);
ssize_t res = 0;unsigned short num = 0;
while(1)
{
bzero(buf, sizeof(buf));
res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen);
if(res < 0)
{
ERR_MSG("recvfrom");
return -1;
}if(3 == buf[1])
{
if(htons(num+1) == *(unsigned short*)(buf+2))
{
num++;if(0 == flag)
{
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if(fd < 0)
{
ERR_MSG("open");
return -1;
}
flag = 1;
}if(write(fd, buf+4, res-2-2) < 0)
{
ERR_MSG("write");
return -1;
}buf[1] = 4;
if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}if(res-2-2 < 512)
{
printf("%s 文件下载完毕\n", filename);
break;
}
}
}
else if(5 == buf[1])
{
fprintf(stderr, "错误码:%d 错误信息:%s\n", ntohs(*(unsigned short*)(buf+2)), buf+4);
break;
}
}close(fd);
return 0;
}int do_upload(int sfd, struct sockaddr_in sin)
{
char str[1000] = "";
char *ptr = str;
short int *ptr1 = (short int*)ptr;
*ptr1 = htons(2);
char *ptr2 = ptr+2;char filename[128] = "";
printf("请输入要上传的文件名>>>");
scanf("%s",filename);
getchar();
strcpy(ptr2,filename);char *ptr3 = ptr2+strlen(ptr2)+1;
strcpy(ptr3,"octet");int size = 2+strlen(ptr2)+1+strlen(ptr3)+1;
if(sendto(sfd, str, size, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success\n");char str1[6] = "";
struct sockaddr_in rcv_addrmsg;
socklen_t addrlen = sizeof(rcv_addrmsg);
if(recvfrom(sfd,str1,sizeof(str1),0,(struct sockaddr*)&rcv_addrmsg,&addrlen) < 0)
{
ERR_MSG("recvfrom");
return -1;
}int fd = open(filename,O_RDONLY);
if(fd<0)
{
ERR_MSG("open");
return -1;
}short int num = 1;
char str2[1024] = "";
ssize_t rts = 0;
while(1)
{
char *sjb = str2;
short int *sjb1 = (short int*)sjb;
*sjb1 = htons(3);short int *sjb2 = (short int*)(sjb+2);
*sjb2 = htons(num);char *sjb3 = (str2+4);
rts = read(fd,sjb3,512);
int sjblen = rts+4;if(sendto(sfd,str2,sjblen,0,(struct sockaddr*)&rcv_addrmsg,addrlen) < 0)
{
ERR_MSG("sendto");
return -1;
}bzero(str1,sizeof(str1));
if(recvfrom(sfd,str1,sizeof(str1),0,(struct sockaddr*)&rcv_addrmsg,&addrlen) < 0)
{
ERR_MSG("recvfrom");
return -1;
}char *ack = str1;
short int *err;
err = (short int*)ack;
if(ntohs(*err) == 5)
{
printf("error:%s\n",(char*)(err+2));
return -1;
}short int *kbh = (short int*)str1;
if(ntohs(*(kbh+1)) != num)
{
continue;
}num++;
if(rts != 512)
{
printf("send file success!\n");
break;
}}
}
下载
上传
上传前
上传后
终端