select实现简单TCP通信(ubuntu 18.04)

一、服务器程序(server.c) 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <strings.h> #define SERV_PORT 9999
#define MAXLINE 4096 #define SA struct sockaddr int max(int, int);
void proSession(FILE*, int, const struct sockaddr*);
ssize_t writen(int, const void*, size_t);
char *sock_ntop(const struct sockaddr*, socklen_t); int main(int argc, char *argv[]) {
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr; listenfd = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); /* 将套接字和套接字地址结构绑定 */ listen(listenfd, ); /* 将套接字转换为监听套接字 */ clilen = sizeof(cliaddr);
if ( (connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) > ) {
proSession(stdin, connfd, (SA *)&cliaddr); /* 处理会话 */
}
exit(0);
} void proSession(FILE *fp, int sockfd, const struct sockaddr *addr) {
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n; stdineof = ;
FD_ZERO(&rset);
for ( ; ; ) {
if (stdineof == ) {
FD_SET(fileno(fp), &rset);
}
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) + ;
select(maxfdp1, &rset, NULL, NULL, NULL); if (FD_ISSET(sockfd, &rset)) { /* 套接字描述符就绪 */
if ( (n = read(sockfd, buf, MAXLINE)) == ) {
if (stdineof == ) {
return;
} else {
exit(0);
}
}
printf("%s\n", sock_ntop(addr, sizeof(addr)));
write(fileno(stdout), buf, n);
printf("\n");
}
if (FD_ISSET(fileno(fp), &rset)) { /* 输入描述符就绪 */
if ( (n = read(fileno(fp), buf, MAXLINE)) == ) {
stdineof = ;
shutdown(sockfd, SHUT_WR); /* 发送 FIN */
FD_CLR(fileno(fp), &rset);
continue;
}
writen(sockfd, buf, n);
}
}
} int max(int numberone, int numbertwo) {
return ( (numberone >= numbertwo)?numberone:numbertwo);
}

二、客户端程序(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h> #define SA struct sockaddr
#define SERV_PORT 9999
#define MAXLINE 4096 int max(int, int);
void proSession(FILE*, int, const struct sockaddr*);
ssize_t writen(int, const void*, size_t);
char *sock_ntop(const struct sockaddr*, socklen_t); int main(int argc, char *argv[]) {
pid_t childpid;
int sockfd;
struct sockaddr_in servaddr; if (argc != ) {
printf("usage: %s <IPaddress>\n", argv[]);
exit(-1);
} sockfd = socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[], &servaddr.sin_addr); if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) == ) {
proSession(stdin, sockfd, (SA *)&servaddr); /* 处理会话 */
} exit(0);
} void proSession(FILE *fp, int sockfd, const struct sockaddr* addr) {
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n; stdineof = ;
FD_ZERO(&rset);
for ( ; ; ) {
if (stdineof == ) {
FD_SET(fileno(fp), &rset);
}
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) + ;
select(maxfdp1, &rset, NULL, NULL, NULL); if (FD_ISSET(sockfd, &rset)) { /* 套接字描述符就绪 */
if ( (n = read(sockfd, buf, MAXLINE)) == ) {
if (stdineof == ) {
return;
} else {
exit(0);
}
}
printf("%s\n", sock_ntop(addr, sizeof(addr)));
write(fileno(stdout), buf, n);
printf("\n");
}
if (FD_ISSET(fileno(fp), &rset)) { /* 输入描述符就绪 */
if ( (n = read(fileno(fp), buf, MAXLINE)) == ) {
stdineof = ;
shutdown(sockfd, SHUT_WR); /* 发送 FIN */
FD_CLR(fileno(fp), &rset);
continue;
}
writen(sockfd, buf, n);
}
}
} int max(int numberone, int numbertwo) {
return ( (numberone >= numbertwo)?numberone:numbertwo);
}

三、服务器程序或客户端程序用到的程序

 (1)sock_ntop.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/socket.h> char *sock_ntop(const struct sockaddr *sa, socklen_t salen) { char portstr[];
static char str[]; switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (inet_ntop(AF_INET, &sin->sin_addr, str,
sizeof(str)) == NULL) {
return(NULL);
}
if (ntohs(sin->sin_port) != ) {
snprintf(portstr, sizeof(portstr), ":%d",
ntohs(sin->sin_port));
strcat(str, portstr);
}
return(str);
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; str[] = '[';
if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + ,
sizeof(str) - ) == NULL) {
return(NULL);
}
if (ntohs(sin6->sin6_port) != ) {
snprintf(portstr, sizeof(portstr), "]:%d",
ntohs(sin6->sin6_port));
strcat(str, portstr);
return(str);
}
return (str + );
}
case AF_UNIX: {
struct sockaddr_un *unp = (struct sockaddr_un *) sa; if (unp->sun_path[] == ) {
strcpy(str, "(no pathname bound)");
} else {
snprintf(str, sizeof(str), "%s", unp->sun_path);
}
return(str);
}
default: {
snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
sa->sa_family, salen);
return(str);
}
}
return (NULL);
}

 (2)writen.c

#include <unistd.h>
#include <errno.h> ssize_t writen(int fd, const void *vptr, size_t n) {
size_t nleft;
ssize_t nwriten;
const char *ptr; ptr = vptr;
nleft = n;
while (nleft > ) {
if ( (nwriten = write(fd, ptr, nleft)) <= ) {
if (nwriten < && errno) {
nwriten = ; /* call write() again */
} else {
return (-); /* error */
}
}
nleft -= nwriten;
ptr += nwriten;
}
return (n - nwriten);
}

四、Makefile文件

 (1)服务器 

target=server
cc=gcc
$(target):writen.o server.o sock_ntop.o
$(cc) sock_ntop.o writen.o server.o -o $(target)
sock_ntop.o:sock_ntop.c
$(cc) -c sock_ntop.c -o sock_ntop.o
writen.o:writen.c
$(cc) -c writen.c -o writen.o
server.o:server.c
$(cc) -c server.c -o server.o
clean:
rm -rf *.o $(target)

 (2)客户端

target=client
cc=gcc
$(target):writen.o client.o sock_ntop.o
$(cc) writen.o client.o sock_ntop.o -o $(target)
writen.o:writen.c
$(cc) -c writen.c -o writen.o
server.o:client.c
$(cc) -c client.c -o client.o
sock_ntop.o:sock_ntop.c
$(cc) -c sock_ntop.c -o sock_ntop.o
clean:
rm -rf *.o $(target)
~
上一篇:【1414软工助教】团队作业6——展示博客(Alpha版本) 得分榜


下一篇:[转帖]计算机性能评测软件