//client_p2p
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
\
}while(0)
struct packet
{
int len;
char buf[1024];
};
void sig(int num)
{
switch (num)
{
case SIGUSR1:
printf("client recv signal %d, exit...\n", num);
exit(0);
break;
default:
break;
}
}
ssize_t readn(int fd, void *buf, size_t count)
{
size_t nleft = count;
ssize_t nread;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nread == 0) //若对方已关闭
return count - nleft;
bufp += nread;
nleft -= nread;
}
return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft = count;
ssize_t nwritten;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nwritten = write(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}
return count;
}
void read_service (int conn)
{
struct packet recvbuf;
int n;
while (1)
{
memset(&recvbuf, 0, sizeof(recvbuf));
int ret = readn(conn, &recvbuf.len, 4);
if (ret == -1)
ERR_EXIT("read failed");
else if (ret < 4)
{
printf("server close\n");
break;
}
n = ntohl(recvbuf.len);
ret = readn(conn, recvbuf.buf, n);
if (ret == -1)
ERR_EXIT("read");
else if (ret < n)
{
printf("server close\n");
break;
}
fputs(recvbuf.buf, stdout);
}
return ;
}
void write_service (int conn)
{
struct packet sendbuf;
int n;
while (1)
{
memset(&sendbuf, 0, sizeof(sendbuf));
if (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) == NULL)
ERR_EXIT("fgets failed");
n = strlen(sendbuf.buf);
sendbuf.len = htonl(n);
writen(conn, &sendbuf, 4 + n);
}
close(conn);
return ;
}
int main()
{
int sockfd;
//建立socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("create socket failed");
return 1;
}
//connect 连接server
struct sockaddr_in serveraddr_in;
memset(&serveraddr_in, 0, sizeof(serveraddr_in));
serveraddr_in.sin_family = AF_INET;
serveraddr_in.sin_port = htons(12345); /* port in network byte order */
serveraddr_in.sin_addr.s_addr = inet_addr("127.0.0.1");
if ( connect(sockfd, (struct sockaddr *)&serveraddr_in, sizeof(serveraddr_in) ) == -1)
{
perror("connect failed");
return 1;
}
if ( signal(SIGUSR1, sig) == SIG_ERR )
{
perror("install signal error");
}
int pid = fork();
if (pid == 0)
{
//业务
while (1)
{
read_service(sockfd);
kill(getppid(), SIGUSR1);
close(sockfd);
exit (1);
}
}
else
{
write_service(sockfd);
}
return 0;
}
//server_p2p
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
\
}while(0)
/*
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
struct in_addr {
uint32_t s_addr;
};
*/
/*
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
*/
struct packet
{
int len;
char buf[1024];
};
void sig(int num)
{
switch (num)
{
case SIGUSR1:
printf("server recv signal %d, exit...\n", num);
exit(1);
break;
default:
break;
}
}
ssize_t readn(int fd, void *buf, size_t count)
{
size_t nleft = count;
ssize_t nread;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nread = read(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nread == 0) //若对方已关闭
return count - nleft;
bufp += nread;
nleft -= nread;
}
return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft = count;
ssize_t nwritten;
char *bufp = (char*)buf;
while (nleft > 0)
{
if ((nwritten = write(fd, bufp, nleft)) < 0)
{
if (errno == EINTR)
continue;
return -1;
}
else if (nwritten == 0)
continue;
bufp += nwritten;
nleft -= nwritten;
}
return count;
}
void read_service (int conn)
{
struct packet recvbuf;
int n;
while (1)
{
memset(&recvbuf, 0, sizeof(recvbuf));
int ret = readn(conn, &recvbuf.len, 4);
if (ret == -1)
ERR_EXIT("read failed");
else if (ret < 4)
{
printf("client close\n");
break;
}
n = ntohl(recvbuf.len);
ret = readn(conn, recvbuf.buf, n);
if (ret == -1)
ERR_EXIT("read");
else if (ret < n)
{
printf("client close\n");
//printf("\n\nclient %s:%d disconn\n\n", inet_ntoa(clientaddr_in.sin_addr), ntohs(clientaddr_in.sin_port));
break;
}
fputs(recvbuf.buf, stdout);
}
return ;
}
void write_service (int conn)
{
struct packet sendbuf;
int n;
while (1)
{
memset(&sendbuf, 0, sizeof(sendbuf));
if (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) == NULL)
ERR_EXIT("fgets failed");
n = strlen(sendbuf.buf);
sendbuf.len = htonl(n);
writen(conn, &sendbuf, 4 + n);
}
close(conn);
return ;
}
int main()
{
int serverfd;
//建立socket
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd == -1)
{
perror("create socket failed");
return 1;
}
//给TCP设置地址可重用
int on = 1;
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
{
printf("setsockopt failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
//bind 绑定端口,IP
struct sockaddr_in serveraddr_in;
memset(&serveraddr_in, 0, sizeof(serveraddr_in));
serveraddr_in.sin_family = AF_INET;
serveraddr_in.sin_port = htons(12345); /* port in network byte order */
serveraddr_in.sin_addr.s_addr = inet_addr("0.0.0.0");
if ( bind(serverfd, (struct sockaddr *)&serveraddr_in, sizeof(serveraddr_in)) == -1)
{
perror("bind failed");
return 1;
}
//listen 被动套接字,监听端口
if (listen(serverfd, 20) == -1)
{
perror("listen failed");
return 1;
}
//while(1)
{
//accept 阻塞等待client连接
int clientfd = -1;
struct sockaddr_in clientaddr_in;
memset(&clientaddr_in, 0, sizeof(clientaddr_in));
socklen_t clientaddr_len = sizeof(clientaddr_in);
if ( (clientfd = accept(serverfd, (struct sockaddr *)&clientaddr_in, &clientaddr_len) ) == -1)
{
perror("accept failed");
return 1;
}
else
{
printf("\n\nclient %s:%d connected\n\n", inet_ntoa(clientaddr_in.sin_addr), ntohs(clientaddr_in.sin_port));
}
if ( signal(SIGUSR1, sig) == SIG_ERR )
{
perror("install signal error");
}
int pid = fork();
if (pid == 0)
{
//子进程关闭被动套接字
close(serverfd);
//业务
while (1)
{
read_service(clientfd);
kill(getppid(), SIGUSR1);
close(clientfd);
exit (1);
}
}
else
{
write_service(clientfd);
}
}
return 0;
}
备份地址: 【Socket PRGM: chat_p2p】