1.多进程并发服务器
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <wait.h>
#define IP "192.168.1.10"
#define PORT 8888
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
typedef void(*handerl_t)(int);
void handler(int sig)
{
while(waitpid(-1, NULL,WNOHANG) > 0);
}
void massage(int newfd, struct sockaddr_in cin);
int main(int argc, const char *argv[])
{
//回收僵尸进程
handerl_t s = signal(17, handler);
if(s == SIG_ERR)
{
ERRMSG("signal");
}
//创建字节流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//填充服务器自身地址族、IP和端口
struct sockaddr_in sin, cin;//sin用于绑定自身地址信息,cin用于存储客户端地址信息
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t cinlen = sizeof(cin);
//绑定到套接字上
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERRMSG("bind");
}
//设置被动监听状态
if(listen(sfd, 10) < 0)
{
ERRMSG("listen");
}
int newfd = 0;
pid_t pid = 0;;
while(1)
{
//获取新的用于通讯的套接字文件描述符(父进程)
newfd = accept(sfd, (struct sockaddr*)&cin, &cinlen);
if(newfd < 0)
{
ERRMSG("accept");
}
printf("connect success\n");
pid = fork();//创建子进程
if(pid > 0)
{
close(newfd);//没有使用到
}else if(pid == 0)
{
close(sfd);//没有使用到
//接收或发送信息
massage(newfd, cin);
close(newfd);
exit(0);//结束子进程
}else
{
ERRMSG("fork");
}
}
//关闭套接字
return 0;
}
void massage(int newfd, struct sockaddr_in cin)
{
while(1)
{
//接收信息(子进程)
char buff[128]="";
ssize_t res = 0;
bzero(buff, sizeof(buff));
res = recv(newfd, buff, sizeof(buff), 0);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("[%d]:%s\n", ntohs(cin.sin_port), buff);
//发送信息(子进程)
strcpy(buff, "receive completed");
if(send(newfd, buff, sizeof(buff), 0) < 0)
{
ERRMSG("send");
}
}
}
测试结果
2.多线程并发服务器
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define IP "192.168.1.10"
#define PORT 8888
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
struct msg
{
int newfd;
struct sockaddr_in cin;
};
void* massage(void* arg);
int main(int argc, const char *argv[])
{
//创建字节流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//填充服务器自身地址族、IP和端口
struct sockaddr_in sin, cin;//sin用于绑定自身地址信息,cin用于存储客户端地址信息
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t cinlen = sizeof(cin);
//绑定到套接字上
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERRMSG("bind");
}
//设置被动监听状态
if(listen(sfd, 10) < 0)
{
ERRMSG("listen");
}
//主线程获取新的用于通讯的套接字文件描述符,子线程用于收发信息
pthread_t tid;
int newfd = 0;
while(1)
{
newfd = accept(sfd, (struct sockaddr*)&cin, &cinlen);
if(newfd < 0)
{
ERRMSG("accept");
}
printf("connect success\n");
struct msg msg;
msg.newfd = newfd;
msg.cin = cin;
pthread_create(&tid, NULL, massage, (void*)&msg);//创建子线程
}
//关闭套接字
close(sfd);
close(newfd);
return 0;
}
void* massage(void* arg)
{
int newfd = (*(struct msg*)arg).newfd;
struct sockaddr_in cin = (*(struct msg*)arg).cin;
while(1)
{
//接收信息(子线程)
char buff[128]="";
ssize_t res = 0;
bzero(buff, sizeof(buff));
res = recv(newfd, buff, sizeof(buff), 0);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("newfd=%d port=[%d]:%s\n", newfd, ntohs(cin.sin_port), buff);
//发送信息(子线程)
strcpy(buff, "receive completed");
if(send(newfd, buff, sizeof(buff), 0) < 0)
{
ERRMSG("send");
}
}
}
测试结果
3.tcp本地通讯
服务器代码:
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/un.h>
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
void* massage(void* arg);
int main(int argc, const char *argv[])
{
//创建字节流式套接字(本地通讯)
int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
if(access(argv[1], F_OK) == 0)
{
if(unlink(argv[1]) < 0)
{
ERRMSG("unlink");
}
}
//填充服务器自身地址信息
struct sockaddr_un sun, cun;//sun用于绑定自身地址信息,cun用于存储客户端地址信息
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, argv[1]);
socklen_t cunlen = sizeof(cun);
//绑定到套接字上
if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) < 0)
{
ERRMSG("bind");
}
//设置被动监听状态
if(listen(sfd, 10) < 0)
{
ERRMSG("listen");
}
//主线程获取新的用于通讯的套接字文件描述符,子线程用于收发信息
pthread_t tid;
int newfd = 0;
while(1)
{
newfd = accept(sfd, (struct sockaddr*)&cun, &cunlen);
if(newfd < 0)
{
ERRMSG("accept");
}
printf("connect success\n");
pthread_create(&tid, NULL, massage, (void*)&newfd);//创建子线程
}
//关闭套接字
close(sfd);
close(newfd);
return 0;
}
void* massage(void* arg)
{
int newfd = *(int*)arg;
while(1)
{
//接收信息(子线程)
char buff[128]="";
ssize_t res = 0;
bzero(buff, sizeof(buff));
res = recv(newfd, buff, sizeof(buff), 0);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("newfd=%d %s\n", newfd, buff);
//发送信息(子线程)
strcpy(buff, "receive completed");
if(send(newfd, buff, sizeof(buff), 0) < 0)
{
ERRMSG("send");
}
}
}
客户端代码
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/un.h>
#define IP "192.168.1.10"
#define PORT 8888
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
int main(int argc, const char *argv[])
{
//创建字节流式套接字(本地通讯)
int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//填充服务器地址信息
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, argv[1]);
//连接服务器
if(connect(sfd, (struct sockaddr*)&sun, sizeof(sun)) <0)
{
ERRMSG("connect");
}
char buff[128]="";
ssize_t res = 0;
while(1)
{
//发送信息
bzero(buff, sizeof(buff));
fgets(buff, sizeof(buff), stdin);
buff[strlen(buff)-1] = '\0';
if(send(sfd, buff, sizeof(buff), 0) < 0)
{
ERRMSG("send");
}
//接收信息
bzero(buff, sizeof(buff));
res = recv(sfd, buff, sizeof(buff), 0);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("%s\n", buff);
}
//关闭套接字
close(sfd);
return 0;
}
测试结果
4.udp本地通讯
服务器代码
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/un.h>
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
int main(int argc, const char *argv[])
{
//创建数据报式套接字(本地通讯)
int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
if(access("./unix", F_OK) == 0)
{
if(unlink("./unix") < 0)
{
ERRMSG("unlink");
}
}
//填充服务器自身地址信息
struct sockaddr_un sun, cun;//sun用于绑定自身地址信息,cun用于存储客户端地址信息
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, "./unix");
socklen_t cunlen = sizeof(cun);
//绑定到套接字上
if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) < 0)
{
ERRMSG("bind");
}
char buff[128]="";
ssize_t res = 0;
//收发信息
while(1)
{
//接收信息
bzero(buff, sizeof(buff));
res = recvfrom(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&cun, &cunlen);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("%s\n", buff);
//发送信息
strcpy(buff, "receive completed");
if(sendto(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&cun, sizeof(cun)) < 0)
{
ERRMSG("send");
}
}
//关闭套接字
close(sfd);
return 0;
}
客户端代码
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/un.h>
#define ERRMSG(msg) do\
{\
fprintf(stderr, "__%d__", __LINE__);\
exit(1);\
}while(0)
int main(int argc, const char *argv[])
{
//创建数据报式套接字(本地通讯)
int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERRMSG("socket");
}
//要绑定的文件是否存在,存在则删除,需要的是由bind创建出来的文件
if(access(argv[1], F_OK) == 0)
{
if(unlink(argv[1]) < 0)
{
ERRMSG("unlink");
}
}
//填充客户端地址信息,不然服务器无法发送信息给客户端
struct sockaddr_un cun;
cun.sun_family = AF_UNIX;
strcpy(cun.sun_path, argv[1]);
//绑定到套接字上
if(bind(sfd, (struct sockaddr*)&cun, sizeof(cun)) < 0)
{
ERRMSG("bind");
}
//填充服务器地址信息
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path, "./unix");
socklen_t sunlen = sizeof(sun);
char buff[128]="";
ssize_t res = 0;
//收发信息
while(1)
{
//发送信息
bzero(buff, sizeof(buff));
fgets(buff, sizeof(buff), stdin);
buff[strlen(buff)-1] = '\0';
if(sendto(sfd, buff, sizeof(buff), 0, (struct sockaddr*)&sun, sizeof(sun)) < 0)
{
ERRMSG("send");
}
//接收信息
bzero(buff, sizeof(buff));
res = recvfrom(sfd, buff, sizeof(buff), 0, NULL, NULL);
if(res < 0)
{
ERRMSG("recv");
}
if(res == 0)
{
break;
}
printf("%s\n", buff);
}
//关闭套接字
close(sfd);
return 0;
}
测试结果