socket 代码学习

2 篇文章 0 订阅
2 篇文章 0 订阅

/*简单的网络编程实例。该实例是一个客户端程序,它首先连接到一个标准时间服务器上,从服务器读取当前时间,然后显示时间。*/

#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#define HOSTNAMELEN 40
#define BUFLEN 1024
#define PORT 13 /* port of daytime server */
int main(int argc, char *argv[])
{
int rc;
int sockfd; /* socket descriptor */
char buf[BUFLEN+1];
char* pc;
struct sockaddr_in sa;
struct hostent* hen;
if (argc < 2) {
fprintf(stderr, "Missing host name\n");
exit (1);
}
/* Address resolution */
hen = gethostbyname(argv[1]);
if (!hen) {
perror("couldn't resolve host name");
}
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(PORT);
memcpy(&sa.sin_addr.s_addr, hen->h_addr_list[0], hen->h_length);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket() failed");
}
rc = connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
if (rc) {
perror("connect() failed");
}
/* reading the socket */
pc = buf;
while (rc = read(sockfd, pc, BUFLEN - (pc-buf))) {
pc += rc;
}
/* close the socket */
close(sockfd);
/* pad a null character to the end of the result */
*pc = '\0';
/* print the result */
printf("Time: %s", buf);
/* and terminate */
return 0;
}

=============================================
//TCP 服务器。该程序等待客户的连接,一旦连接,则显示客户IP 地址,并发信息回客户。


#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 1 /* Number of allowed connections */
main()
{
int listenfd, connectfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
/* set socket can be reused */
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server)); /* fill server with 0s */
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
/* calls accept() */
perror("accept() error\n");
exit(1);
}
printf("You got a connection from %s\n",inet_ntoa(client.sin_addr) ); /* prints client's IP */
send(connectfd,"Welcome to my server.\n",22,0); /* send to the client welcome message */
close(connectfd); /* close connectfd */
close(listenfd); /* close listenfd */
}

=============================================

// TCP 客户机。该程序完成了TCP 套接字客户端的基本过程。

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* netbd.h is needed for struct hostent */
#define PORT 1234 /* Open Port on Remote Host */
#define MAXDATASIZE 100 /* Max number of bytes of data */
int main(int argc, char *argv[])
{
int fd, numbytes; /* files descriptors */
char buf[MAXDATASIZE]; /* buf will store received text */
struct hostent *he; /* structure that will get information about remote host */
struct sockaddr_in server; /* server's address information */
if (argc !=2) { /* this is used because our program will need one argument (IP) */
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){ /* calls socket() */
printf("socket() error\n");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT); /* htons() is needed again */
server.sin_addr = *((in_addr *)he->h_addr); /*he->h_addr passes "*he"'s info to "h_addr" */
if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1){ /* calls connect() */
printf("connect() error\n");
exit(1);
}
if ((numbytes=recv(fd,buf,MAXDATASIZE,0)) == -1){ /* calls recv() */
printf("recv() error\n");
exit(1);
}
buf[numbytes]='\0';
printf("Server Message: %s\n",buf); /* it prints server's welcome message */
close(fd); /* close fd */
}

========================================
// UDP 服务器。该程序执行UDP 套接字服务端的基本过程。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define MAXDATASIZE 100 /* Max number of bytes of data */
main()
{
int sockfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
int num;
char msg[MAXDATASIZE]; /* buffer for message */
/* Creating UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while (1) {
num = recvfrom(sockfd,msg,MAXDATASIZE,0,(struct sockaddr *)&client,&sin_size);
if (num < 0){
perror("recvfrom error\n");
exit(1);
}
msg[num] = '\0';
printf("You got a message (%s%) from %s\n",msg,inet_ntoa(client.sin_addr) ); /* prints client's IP */
sendto(sockfd,"Welcome to my server.\n",22,0,(struct sockaddr *)&client,sin_size); /* send to the client
welcome message */
if (!strcmp(msg,"quit")) break;
}
close(sockfd); /* close listenfd */
}

==========================================================
// UDP 客户。该程序通过命令行参数输入服务器IP 地址和发给服务器的信息,然后执行UDP 套接字客户端的基本过程。

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* netbd.h is needed for struct hostent =) */
#define PORT 1234 /* Open Port on Remote Host */
#define MAXDATASIZE 100 /* Max number of bytes of data */
int main(int argc, char *argv[])
{
int fd, numbytes; /* files descriptors */
char buf[MAXDATASIZE]; /* buf will store received text */
struct hostent *he; /* structure that will get information about remote host */
struct sockaddr_in server,reply; /* server's address information */
if (argc !=3) { /* this is used because our program will need two argument (IP address and a message */
printf("Usage: %s <IP Address> <message>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1){ /* calls socket() */
printf("socket() error\n");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT); /* htons() is needed again */
server.sin_addr = *((struct in_addr *)he->h_addr); /*he->h_addr passes "*he"'s info to "h_addr" */
sendto(fd, argv[2], strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(struct sockaddr));
while (1) {
int len;
if ((numbytes=recvfrom(fd,buf,MAXDATASIZE,0,(struct sockaddr *)&reply,&len)) == -1){ /* calls recvfrom() */
printf("recvfrom() error\n");
exit(1);
}
if (len != sizeof(struct sockaddr) || memcmp((const void *)&server, (const void *)&reply,len) != 0) {
printf("Receive message from other server.\n");
continue;
}
buf[numbytes]='\0';
printf("Server Message: %s\n",buf); /* it prints server's welcome message */
break;
}
close(fd); /* close fd */
}

====================================================
// 重复性服务器。该程序等候客户连接,一旦连接则显示客户的地址,然后接收来自该客户的信息(字符串)。每当收到一个字符串,则显示该字符串,并将字符串反转,
//再将反转的字符发回客户。之后,继续等待接收该客户的信息直至该客户关闭连接。完成与该客户交互后,服务器开始等待下一客户,并重复上述过程。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 5 /* Number of allowed connections */
#define MAXDATASIZE 1000
void process_cli(int connectfd, sockaddr_in client);
main()
{
int listenfd, connectfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while (1) {
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
process_cli(connectfd, client);
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE];
printf("You got a connection from %s\n",inet_ntoa(client.sin_addr) ); /* prints client's IP */
while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client message: %s",recvbuf);
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
send(connectfd,sendbuf,strlen(sendbuf),0); /* send to the client welcome message */
}
close(connectfd); /* close connectfd */
}
==========================================
// 客户端程序。该程序首先与相应服务器连接。然后接收用户从标准输入(键盘)输入的字符串,再将字符串发送给服务器,接收服务器发回的信息并显示。之后,继续
//等待用户输入直至用户输入Ctrl-D。当收到用户输入Ctrl-D 后,客户关闭连接并退出。

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* netbd.h is needed for struct hostent =) */
#define PORT 1234 /* Open Port on Remote Host */
#define MAXDATASIZE 1000 /* Max number of bytes of data */
void process(FILE *fp, int sockfd);
int main(int argc, char *argv[])
{
int fd; /* files descriptors */
struct hostent *he; /* structure that will get information about remote host */
struct sockaddr_in server; /* server's address information */
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){ /* calls socket() */
printf("socket() error\n");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT); /* htons() is needed again */
server.sin_addr = *((struct in_addr *)he->h_addr);
if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1){ /* calls connect() */
printf("connect() error\n");
exit(1);
}
process(stdin,fd);
close(fd); /* close fd */
}
void process(FILE *fp, int sockfd)
{
char sendline[MAXDATASIZE], recvline[MAXDATASIZE];
int numbytes;
printf("Connected to server. \n");
while (fgets(sendline, MAXDATASIZE, fp) != NULL) {
send(sockfd, sendline, strlen(sendline),0);
if ((numbytes = recv(sockfd, recvline, MAXDATASIZE,0)) == 0) {
printf("Server terminated.\n");
return;
}
recvline[numbytes]='\0';
printf("Server Message: %s\n",recvline); /* it prints server's welcome message */
}
}

===============================================
//  多进程并发服务器。该程序等候客户连接,一旦连接则显示客户的地址,接着接收该客户的名字并显示。然后接收来自该客户的信息(字符串)。每当收到一个字符串,
//则显示该字符串,并将字符串反转,再将反转的字符发回客户。之后,继续等待接收该客户的信息直至该客户关闭连接。服务器具有同时处理多客户的能力。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
#define MAXDATASIZE 1000
void process_cli(int connectfd, sockaddr_in client);
main()
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/*accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* Create child process to service client */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/*child process*/
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) ); /* prints client's IP */
/* Get client's name from client */
num = recv(connectfd, cli_name, MAXDATASIZE,0);
if (num == 0) {
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num - 1] = '\0';
printf("Client's name is %s.\n",cli_name);
while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client( %s ) message: %s",cli_name, recvbuf);
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
send(connectfd,sendbuf,strlen(sendbuf),0); /* send to the client welcome message */
}
close(connectfd); /* close connectfd */
}

=======================================================
// 客户程序。该程序首先与相应服务器连接。接着接收用户从标准输入(键盘)输入的客户名字,再将名字发送给服务器。然后接收用户从标准输入(键盘)输入的字符串,
//再将字符串发送给服务器,接收服务器发回的信息并显示。之后,继续等待用户输入直至用户输入Ctrl-D。当收到用户输入Ctrl-D 后,客户关闭连接并退出。

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* netbd.h is needed for struct hostent =) */
#define PORT 1234 /* Open Port on Remote Host */
#define MAXDATASIZE 100 /* Max number of bytes of data */
void process(FILE *fp, int sockfd);
char* getMessage(char* sendline,int len, FILE* fp);
int main(int argc, char *argv[])
{
int fd; /* files descriptors */
struct hostent *he; /* structure that will get information about remote host */
struct sockaddr_in server; /* server's address information */
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){ /* calls socket() */
printf("socket() error\n");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT); /* htons() is needed again */
server.sin_addr = *((struct in_addr *)he->h_addr);
if(connect(fd, (struct sockaddr *)&server,sizeof(struct sockaddr))==-1){ /* calls connect() */
printf("connect() error\n");
exit(1);
}
process(stdin,fd);
close(fd); /* close fd */
}
void process(FILE *fp, int sockfd)
{
char sendline[MAXDATASIZE], recvline[MAXDATASIZE];
int numbytes;
printf("Connected to server. \n");
/* send name to server */
printf("Input name : ");
if ( fgets(sendline, MAXDATASIZE, fp) == NULL) {
printf("\nExit.\n");
return;
}
send(sockfd, sendline, strlen(sendline),0);
/* send message to server */
while (getMessage(sendline, MAXDATASIZE, fp) != NULL) {
send(sockfd, sendline, strlen(sendline),0);
if ((numbytes = recv(sockfd, recvline, MAXDATASIZE,0)) == 0) {
printf("Server terminated.\n");
return;
}
recvline[numbytes]='\0';
printf("Server Message: %s\n",recvline); /* it prints server's welcome message */
}
printf("\nExit.\n");
}
char* getMessage(char* sendline,int len, FILE* fp)
{
printf("Input string to server:");
return(fgets(sendline, MAXDATASIZE, fp));
}

==============================================================
//多线程并发服务器。该程序实现多线程并发服务器。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 5 /* Number of allowed connections */
#define MAXDATASIZE 1000
void process_cli(int connectfd, sockaddr_in client);
/* function to be executed by the new thread */
void* start_routine(void* arg);
struct ARG {
int connfd;
sockaddr_in client;
};
main()
{
int listenfd, connectfd; /* socket descriptors */
pthread_t thread;
ARG *arg;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* Accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* Create thread*/
arg = new ARG;
arg->connfd = connectfd;
memcpy((void *)&arg->client, &client, sizeof(client));
if (pthread_create(&thread, NULL, start_routine, (void*)arg)) {
/* handle exception */
perror("Pthread_create() error");
exit(1);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) );
/* Get client's name from client */
num = recv(connectfd, cli_name, MAXDATASIZE,0);
if (num == 0) {
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num - 1] = '\0';
printf("Client's name is %s.\n",cli_name);
while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client( %s ) message: %s",cli_name, recvbuf);
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
send(connectfd,sendbuf,strlen(sendbuf),0);
}
close(connectfd); /* close connectfd */
}
void* start_routine(void* arg)
{
ARG *info;
info = (ARG *)arg;
/* handle client’s requirement */
process_cli(info->connfd, info->client);
delete arg;
pthread_exit(NULL);
}

========================================================
//线程安全实例。该程序说明线程安全问题。该例子实现的功能与多线程并发服务器实例的类似,但增加了一个客户数据存储功能,即服务器将存储每个连接客户所发
//来的所有数据,当连接终止后,服务将显示客户的名字及相应的数据。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
void process_cli(int connectfd, sockaddr_in client);
main(int argc, char* argv[])
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* create child process */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
sockaddr_in address;
int namelen;
getsockname(connectfd, (sockaddr *)&address, &namelen);
printf("Connected to address ( %s )\n ",inet_ntoa(address.sin_addr) );
close(connectfd); /* close connectfd */
}

================================================
//TSD 线程安全实例。该程序采用TSD 方法解决线程安全问题。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
void process_cli(int connectfd, sockaddr_in client);
main(int argc, char* argv[])
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* create child process */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
sockaddr_in address;
int namelen;
getsockname(connectfd, (sockaddr *)&address, &namelen);
printf("Connected to address ( %s )\n ",inet_ntoa(address.sin_addr) );
close(connectfd); /* close connectfd */
}

==============================================
// 通过使用函数的参变量实现线程安全的实例。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 5 /* Number of allowed connections */
#define MAXDATASIZE 1000
typedef struct DATA_THR{
int index;
};
void process_cli(int connectfd, sockaddr_in client);
void savedata(char* recvbuf, int len, char* cli_data, DATA_THR* data);
/* function to be executed by the new thread */
void* start_routine(void* arg);
struct ARG {
int connfd;
sockaddr_in client;
};
main()
{
int listenfd, connectfd; /* socket descriptors */
pthread_t thread;
ARG *arg;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* Accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* create thread */
arg = new ARG;
arg->connfd = connectfd;
memcpy((void *)&arg->client, &client, sizeof(client));
if (pthread_create(&thread, NULL, start_routine, (void*)arg)) {
/* handle exception */
perror("Pthread_create() error");
exit(1);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
DATA_THR data;
char cli_data[5000];
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
data.index = 0;
printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) ); /* prints client's IP */
/* Get client's name from client */
num = recv(connectfd, cli_name, MAXDATASIZE,0);
if (num == 0) {
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num - 1] = '\0';
printf("Client's name is %s.\n",cli_name);
while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client( %s ) message: %s",cli_name, recvbuf);
/* save user's data */
savedata(recvbuf,num,cli_data, &data);
/* reverse usr's data */
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
send(connectfd,sendbuf,strlen(sendbuf),0); /* send to the client welcome message */
}
close(connectfd); /* close connectfd */
printf("Client( %s ) closed connection. User's data: %s\n",cli_name,cli_data);
}
void* start_routine(void* arg)
{
ARG *info;
info = (ARG *)arg;
/* handle client */
process_cli(info->connfd, info->client);
delete info;
pthread_exit(NULL);
}
void savedata(char* recvbuf, int len, char* cli_data, DATA_THR* data)
{
for (int i = 0; i < len - 1; i++) {
cli_data[data->index++] = recvbuf[i];
}
cli_data[data->index] = '\0';
}

===================================================
// 单线程并发服务器实例。该程序采用单线程并发服务器算法实现的。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <stdlib.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 5 /* Number of allowed connections */
#define MAXDATASIZE 1000
typedef struct CLIENT{
int fd;
char* name;
struct sockaddr_in addr; /* client's address information */
char* data;
};
void process_cli(CLIENT *client, char* recvbuf, int len);
void savedata(char* recvbuf, int len, char* data);
main()
{
int i, maxi, maxfd,sockfd;
int nready;
ssize_t n;
fd_set rset, allset;
int listenfd, connectfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
/* client's information */
CLIENT client[FD_SETSIZE];
char recvbuf[MAXDATASIZE];
int sin_size;
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
/*initialize for select */
maxfd = listenfd;
maxi = -1;
for (i = 0; i < FD_SETSIZE; i++) {
client[i].fd = -1;
}
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
while(1)
{
struct sockaddr_in addr;
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
/* Accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&addr,&sin_size))==-1) {
perror("accept() error\n");
continue;
}
/* Put new fd to client */
for (i = 0; i < FD_SETSIZE; i++)
if (client[i].fd < 0) {
client[i].fd = connectfd; /* save descriptor */
client[i].name = new char[MAXDATASIZE];
client[i].addr = addr;
client[i].data = new char[MAXDATASIZE];
client[i].name[0] = '\0';
client[i].data[0] = '\0';
printf("You got a connection from %s. ",inet_ntoa(client[i].addr.sin_addr) );
break;
}
if (i == FD_SETSIZE) printf("too many clients\n");
FD_SET(connectfd, &allset); /* add new descriptor to set */
if (connectfd > maxfd) maxfd = connectfd;
if (i > maxi) maxi = i;
if (--nready <= 0) continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i].fd) < 0) continue;
if (FD_ISSET(sockfd, &rset)) {
if ( (n = recv(sockfd, recvbuf, MAXDATASIZE,0)) == 0) {
/*connection closed by client */
close(sockfd);
printf("Client( %s ) closed connection. User's data: %s\n",client[i].name,client[i].data);
FD_CLR(sockfd, &allset);
client[i].fd = -1;
delete client[i].name;
delete client[i].data;
} else
process_cli(&client[i], recvbuf, n);
if (--nready <= 0) break; /* no more readable descriptors */
}
}
}
close(listenfd); /* close listenfd */
}
void process_cli(CLIENT *client, char* recvbuf, int len)
{
char sendbuf[MAXDATASIZE];
recvbuf[len-1] = '\0';
if (strlen(client->name) == 0) {
/* Got client's name from client */
memcpy(client->name,recvbuf, len);
printf("Client's name is %s.\n",client->name);
return;
}
/* save client's data */
printf("Received client( %s ) message: %s\n",client->name, recvbuf);
/* save user's data */
savedata(recvbuf,len, client->data);
/* reverse usr's data */
for (int i1 = 0; i1 < len - 1; i1++) {
sendbuf[i1] = recvbuf[len - i1 -2];
}
sendbuf[len - 1] = '\0';
send(client->fd,sendbuf,strlen(sendbuf),0);
}
void savedata(char* recvbuf, int len, char* data)
{
int start = strlen(data);
for (int i = 0; i < len; i++) {
data[start + i] = recvbuf[i];
}
}
================================================
// 主机名转换为IP 地址程序。该程序通过用户输入的主机名获得主机实体,然
后显示主机的正式名字、别名和IP 地址。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
main(int argc, const char **argv)
{
ulong_t addr;
struct hostent *hp;
char **p;
if (argc != 2) {
(void) printf("usage: %s host_name\n", argv[0]);
exit (1);
}
hp = gethostbyname(argv[1]);
if (hp == NULL) {
(void) printf("host information for %s not found\n", argv[1]);
exit (2);
}
for (p = hp->h_addr_list; *p != 0; p++) {
struct in_addr in;
char **q;
(void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
(void) printf("%s\t%s", inet_ntoa(in), hp->h_name);
for (q = hp->h_aliases; *q != 0; q++)
(void) printf(" %s", *q);
(void) putchar('\n');
}
exit (0);
}
=========================================
// IP 地址转换为主机名程序。该程序通过用户输入的字符串形式的IP 地址获
得主机实体,然后显示主机的正式名字、别名和IP 地址。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
main(int argc, const char **argv)
{
ulong_t addr;
struct hostent *hp;
char **p;
if (argc != 2) {
(void) printf("usage: %s IP-address\n", argv[0]);
exit (1);
}
if ((int)(addr = inet_addr(argv[1])) == -1) {
(void) printf("IP-address must be of the form a.b.c.d\n");
exit (2);
}
hp = gethostbyaddr((char *)&addr, sizeof (addr), AF_INET);
if (hp == NULL) {
(void) printf("host information for %s not found\n", argv[1]);
exit (3);
}
for (p = hp->h_addr_list; *p != 0; p++) {
struct in_addr in;
char **q;
(void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
(void) printf("%s\t%s", inet_ntoa(in), hp->h_name);
for (q = hp->h_aliases; *q != 0; q++)
(void) printf(" %s", *q);
(void) putchar('\n');
}
exit (0);
}

===============================================
// 互斥对象实例。该程序说明如何使用互斥对象。

#include <stdio.h>
#include <pthread.h> /* pthread functions and data structures */
#define NUM_EMPLOYEES 2 /* size of each array. */
/* global mutex for our program. assignment initializes it */
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;
struct employee {
int number;
int id;
char first_name[20];
char last_name[30];
char department[30];
int room_number;
};
/* global variable - our employees array, with 2 employees */
struct employee employees[] = {
{ 1, 12345678, "three", "zhang", "Accounting", 101},
{ 2, 87654321, "four", "li", "Programmers", 202}
};
/* global variable - employee of the day. */
struct employee winner;
/* function to copy one employee struct into another */
void copy_employee(struct employee* from, struct employee* to)
{
int rc; /* contain mutex lock/unlock results */
/* lock the mutex, to assure exclusive access to 'a' and 'b'. */
rc = pthread_mutex_lock(&a_mutex);
to->number = from->number;
to->id = from->id;
strcpy(to->first_name, from->first_name);
strcpy(to->last_name, from->last_name);
strcpy(to->department, from->department);
to->room_number = from->room_number;
/* unlock mutex */
rc = pthread_mutex_unlock(&a_mutex);
}
/* function to be executed by the variable setting threads thread */
void* do_loop(void* data)
{
int my_num = *((int*)data); /* thread identifying number */
while (1) {
/* set employee of the day to be the one with number 'my_num'. */
copy_employee(&employees[my_num-1], &winner);
}
}
/* main thread*/
int main(int argc, char* argv[])
{
int i; /* loop counter */
int thr_id1; /* thread ID for the first new thread */
int thr_id2; /* thread ID for the second new thread */
pthread_t p_thread1; /* first thread's structure */
pthread_t p_thread2; /* second thread's structure */
int num1 = 1; /* thread 1 employee number */
int num2 = 2; /* thread 2 employee number */
struct employee eotd; /* local copy of 'winner'. */
struct employee* worker; /* pointer to currently checked employee */
/* initialize winner to first 1. */
copy_employee(&employees[0], &winner);
/* create a new thread that will execute 'do_loop()' with '1' */
thr_id1 = pthread_create(&p_thread1, NULL, do_loop, (void*)&num1);
/* create a second thread that will execute 'do_loop()' with '2' */
thr_id2 = pthread_create(&p_thread2, NULL, do_loop, (void*)&num2);
/* run a loop that verifies integrity of 'winner' many */
for (i=0; i<10000; i++) {
/* save contents of 'winner' to local 'worker'. */
copy_employee(&winner, &eotd);
worker = &employees[eotd.number-1];
/* compare employees */
if (eotd.id != worker->id) {
printf("mismatching 'id' , %d != %d (loop '%d')\n",eotd.id, worker->id, i);
exit(0);
}
if (strcmp(eotd.first_name, worker->first_name) != 0) {
printf("mismatching 'first_name' , %s != %s (loop '%d')\n",eotd.first_name, worker- >first_name, i);
exit(0);
}
if (strcmp(eotd.last_name, worker->last_name) != 0) {
printf("mismatching 'last_name' , %s != %s (loop '%d')\n",eotd.last_name, worker- >last_name, i);
exit(0);
}
if (strcmp(eotd.department, worker->department) != 0) {
printf("mismatching 'department' , %s != %s (loop '%d')\n",eotd.department, worker->department, i);
exit(0);
}
if (eotd.room_number != worker->room_number) {
printf("mismatching 'room_number' , %d != %d (loop '%d')\n",eotd.room_number, worker->room_number, i);
exit(0);
}
}
printf("Employees contents was always consistent\n");
return 0;
}

// 条件变量实例。该程序是一个多线程的无连接并发服务器。

#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
#include <stdlib.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define NUM_HANDLER_THREADS 3 /* number of threads used to service requests */
#define PORT 1234 /* Port that will be opened */
#define MAXDATASIZE 100 /* Max number of bytes of data */
pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t got_request = PTHREAD_COND_INITIALIZER;
int num_requests = 0; /* number of pending requests, initially none */
int sockfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* format of a single request. */
struct request {
char info[MAXDATASIZE]; /* client's data */
struct request* next; /* pointer to next request, NULL if none. */
};
struct request* requests = NULL; /* head of linked list of requests. */
struct request* last_request = NULL; /* pointer to last request. */
void add_request(char* info, pthread_mutex_t* p_mutex, pthread_cond_t* p_cond_var)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
/* create structure with new request */
a_request = (struct request*)malloc(sizeof(struct request));
if (!a_request) { /* malloc failed? */
fprintf(stderr, "add_request: out of memory\n");
exit(1);
}
memcpy(a_request->info, info, MAXDATASIZE);
a_request->next = NULL;
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
/* add new request to the end of the list, updating list */
/* pointers as required */
if (num_requests == 0) { /* special case - list is empty */
requests = a_request;
last_request = a_request;
}
else {
last_request->next = a_request;
last_request = a_request;
}
/* increase total number of pending requests by one. */
num_requests++;
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* signal the condition variable - there's a new request to handle */
rc = pthread_cond_signal(p_cond_var);
}
struct request* get_request(pthread_mutex_t* p_mutex)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
if (num_requests > 0) {
a_request = requests;
requests = a_request->next;
if (requests == NULL) { /* this was the last request on the list */
last_request = NULL;
}
/* decrease the total number of pending requests */
num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* return the request to the caller. */
return a_request;
}
void handle_request(struct request* a_request, int thread_id)
{
char msg[MAXDATASIZE+40];
if (a_request) {
printf("Thread '%d' handled request '%s'\n", thread_id, a_request->info);
fflush(stdout);
sprintf(msg,"Thread '%d' handled your request '%s'\n", thread_id, a_request->info);
sendto(sockfd,msg,strlen(msg),0,(struct sockaddr *)&client,sin_size);
}
}
void* handle_requests_loop(void* data)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
int thread_id = *((int*)data); /* thread identifying number */
/* lock the mutex, to access the requests list exclusively. */
rc = pthread_mutex_lock(&request_mutex);
while (1) {
if (num_requests > 0) { /* a request is pending */
a_request = get_request(&list_mutex);
if (a_request) { /* got a request - handle it and free it */
rc = pthread_mutex_unlock(&list_mutex);
free(a_request);
}
}
else {
rc = pthread_cond_wait(&got_request, &request_mutex);
}
}
}
int main(int argc, char* argv[])
{
int thr_id[NUM_HANDLER_THREADS]; /* thread IDs */
pthread_t p_threads[NUM_HANDLER_THREADS]; /* thread's structures */
int num;
char msg[MAXDATASIZE];
/* create the request-handling threads */
for (int i=0; i<NUM_HANDLER_THREADS; i++) {
thr_id[i] = i;
pthread_create(&p_threads[i], NULL, handle_requests_loop, (void*)&thr_id[i]);
}
/* Create UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while (1)
{
num = recvfrom(sockfd,msg,MAXDATASIZE,0,(struct sockaddr *)&client,&sin_size);
if (num < 0){
perror("recvfrom error\n");
exit(1);
}
msg[num] = '\0';
printf("You got a message (%s%) from %s\n",msg,inet_ntoa(client.sin_addr) ); /* prints client's IP */
add_request(msg, &list_mutex, &got_request);
if (!strcmp(msg,"quit")) break;
}
close(sockfd); /* close listenfd */
return 0;
}
prg8_3.c : 处理同步线程退出。
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
#include <stdlib.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* number of threads used to service requests */
#define NUM_HANDLER_THREADS 3
#define PORT 1234 /* Port that will be opened */
#define MAXDATASIZE 100 /* Max number of bytes of data */
pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t got_request = PTHREAD_COND_INITIALIZER;
int quit; /* 1 means all thread will quit */
int num_requests = 0; /* number of pending requests, initially none */
int sockfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* format of a single request. */
struct request {
char info[MAXDATASIZE]; /* client' data */
struct request* next; /* pointer to next request, NULL if none. */
};
struct request* requests = NULL; /* head of linked list of requests. */
struct request* last_request = NULL; /* pointer to last request. */
void add_request(char* info, pthread_mutex_t* p_mutex, pthread_cond_t* p_cond_var)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
/* create structure with new request */
a_request = (struct request*)malloc(sizeof(struct request));
if (!a_request) { /* malloc failed?? */
fprintf(stderr, "add_request: out of memory\n");
exit(1);
}
memcpy(a_request->info, info, MAXDATASIZE);
a_request->next = NULL;
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
/* add new request to the end of the list, updating list */
/* pointers as required */
if (num_requests == 0) { /* special case - list is empty */
requests = a_request;
last_request = a_request;
}
else {
last_request->next = a_request;
last_request = a_request;
}
/* increase total number of pending requests by one. */
num_requests++;
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* signal the condition variable - there's a new request to handle */
rc = pthread_cond_signal(p_cond_var);
}
struct request* get_request(pthread_mutex_t* p_mutex)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
if (num_requests > 0) {
a_request = requests;
requests = a_request->next;
if (requests == NULL) { /* this was the last request on the list */
last_request = NULL;
}
/* decrease the total number of pending requests */
num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* return the request to the caller. */
return a_request;
}
void handle_request(struct request* a_request, int thread_id)
{
char msg[MAXDATASIZE+40];
if (a_request) {
printf("Thread '%d' handled request '%s'\n", thread_id, a_request->info);
fflush(stdout);
sprintf(msg,"Thread '%d' handled your request '%s'\n", thread_id, a_request->info);
sendto(sockfd,msg,strlen(msg),0,(struct sockaddr *)&client,sin_size);
}
}
void* handle_requests_loop(void* data)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
int thread_id = *((int*)data); /* thread identifying number */
/* lock the mutex, to access the requests list exclusively. */
rc = pthread_mutex_lock(&request_mutex);
while (1) {
if (num_requests > 0) { /* a request is pending */
a_request = get_request(&list_mutex);
/* got a request */
if (a_request) {
/*handle request */
handle_request(a_request, thread_id);
/* free it */
free(a_request);
}
}
else {
if (quit) {
pthread_mutex_unlock(&request_mutex); // unlock mutex before exit
pthread_exit(NULL);
}
rc = pthread_cond_wait(&got_request, &request_mutex);
}
}
}
int main(int argc, char* argv[])
{
int thr_id[NUM_HANDLER_THREADS]; /* thread IDs */
pthread_t p_threads[NUM_HANDLER_THREADS]; /* thread's structures */
int num;
char msg[MAXDATASIZE];
quit = 0;
/* create the request-handling threads */
for (int i=0; i<NUM_HANDLER_THREADS; i++) {
thr_id[i] = i;
pthread_create(&p_threads[i], NULL, handle_requests_loop, (void*)&thr_id[i]);
}
/* Create UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while (1)
{
num = recvfrom(sockfd,msg,MAXDATASIZE,0,(struct sockaddr *)&client,&sin_size);
if (num < 0){
perror("recvfrom error\n");
exit(1);
}
msg[num] = '\0';
printf("You got a message (%s%) from %s\n",msg,inet_ntoa(client.sin_addr) );
add_request(msg, &list_mutex, &got_request);
if (!strcmp(msg,"quit")) {
/* notify our threads we're done . */
int rc;
rc = pthread_mutex_lock(&request_mutex);
quit = 1;
rc = pthread_cond_broadcast(&got_request);
rc = pthread_mutex_unlock(&request_mutex);
/* wait until other thread quit */
for (int i=0; i<NUM_HANDLER_THREADS; i++) {
pthread_join(p_threads[i], NULL);
}
break;
}
}
close(sockfd); /* close listenfd */
return 0;
}
=======================================
// 服务器死锁实例。该程序说明死锁是如何产生的。
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
#include <stdlib.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* number of threads used to service requests */
#define NUM_HANDLER_THREADS 3
#define PORT 1234 /* Port that will be opened */
#define MAXDATASIZE 100 /* Max number of bytes of data */
pthread_mutex_t request_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t got_request = PTHREAD_COND_INITIALIZER;
int quit; /* 1 means all thread will quit */
int num_requests = 0; /* number of pending requests, initially none */
int sockfd; /* socket descriptors */
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* format of a single request. */
struct request {
char info[MAXDATASIZE]; /* client' data */
struct request* next; /* pointer to next request, NULL if none. */
};
struct request* requests = NULL; /* head of linked list of requests. */
struct request* last_request = NULL; /* pointer to last request. */
void add_request(char* info, pthread_mutex_t* p_mutex, pthread_cond_t* p_cond_var)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
/* create structure with new request */
a_request = (struct request*)malloc(sizeof(struct request));
if (!a_request) { /* malloc failed?? */
fprintf(stderr, "add_request: out of memory\n");
exit(1);
}
memcpy(a_request->info, info, MAXDATASIZE);
a_request->next = NULL;
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
/* add new request to the end of the list, updating list */
/* pointers as required */
if (num_requests == 0) { /* special case - list is empty */
requests = a_request;
last_request = a_request;
}
else {
last_request->next = a_request;
last_request = a_request;
}
/* increase total number of pending requests by one. */
num_requests++;
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* signal the condition variable - there's a new request to handle */
rc = pthread_cond_signal(p_cond_var);
}
struct request* get_request(pthread_mutex_t* p_mutex)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
/* lock the mutex, to assure exclusive access to the list */
rc = pthread_mutex_lock(p_mutex);
if (num_requests > 0) {
a_request = requests;
requests = a_request->next;
if (requests == NULL) { /* this was the last request on the list */
last_request = NULL;
}
/* decrease the total number of pending requests */
num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/* return the request to the caller. */
return a_request;
}
void handle_request(struct request* a_request, int thread_id)
{
char msg[MAXDATASIZE+40];
if (a_request) {
printf("Thread '%d' handled request '%s'\n", thread_id, a_request->info);
fflush(stdout);
sprintf(msg,"Thread '%d' handled your request '%s'\n", thread_id, a_request->info);
sendto(sockfd,msg,strlen(msg),0,(struct sockaddr *)&client,sin_size);
}
}
void* handle_requests_loop(void* data)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
int thread_id = *((int*)data); /* thread identifying number */
/* lock the mutex, to access the requests list exclusively. */
rc = pthread_mutex_lock(&request_mutex);
while (1) {
if (num_requests > 0) { /* a request is pending */
a_request = get_request(&list_mutex);
/* got a request */
if (a_request) {
/*handle request */
handle_request(a_request, thread_id);
/* free it */
free(a_request);
}
}
else {
if (quit) {
pthread_mutex_unlock(&request_mutex); // unlock mutex before exit
pthread_exit(NULL);
}
rc = pthread_cond_wait(&got_request, &request_mutex);
}
}
}
int main(int argc, char* argv[])
{
int thr_id[NUM_HANDLER_THREADS]; /* thread IDs */
pthread_t p_threads[NUM_HANDLER_THREADS]; /* thread's structures */
int num;
char msg[MAXDATASIZE];
quit = 0;
/* create the request-handling threads */
for (int i=0; i<NUM_HANDLER_THREADS; i++) {
thr_id[i] = i;
pthread_create(&p_threads[i], NULL, handle_requests_loop, (void*)&thr_id[i]);
}
/* Create UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while (1)
{
num = recvfrom(sockfd,msg,MAXDATASIZE,0,(struct sockaddr *)&client,&sin_size);
if (num < 0){
perror("recvfrom error\n");
exit(1);
}
msg[num] = '\0';
printf("You got a message (%s%) from %s\n",msg,inet_ntoa(client.sin_addr) );
add_request(msg, &list_mutex, &got_request);
if (!strcmp(msg,"quit")) {
/* notify our threads we're done . */
int rc;
rc = pthread_mutex_lock(&request_mutex);
quit = 1;
rc = pthread_cond_broadcast(&got_request);
rc = pthread_mutex_unlock(&request_mutex);
/* wait until other thread quit */
for (int i=0; i<NUM_HANDLER_THREADS; i++) {
pthread_join(p_threads[i], NULL);
}
break;
}
}
close(sockfd); /* close listenfd */
return 0;
}
=============================================
// 僵死进程处理程序。该程序捕获SIGCHLD 信号,然后调用waitid 函数处理僵死进程。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
#define MAXDATASIZE 1000
void process_cli(int connectfd, sockaddr_in client);
void sig_handler(int s);
main()
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
struct sigaction act, oact;
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGCHLD, &act, &oact) < 0) {
perror("Sigaction failed!");
exit(1);
}
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
if (errno == EINTR) continue;
perror("accept() error\n");
exit(1);
}
/* create child process */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) );
/* Get client's name from client */
num = recv(connectfd, cli_name, MAXDATASIZE,0);
if (num == 0) {
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num - 1] = '\0';
printf("Client's name is %s.\n",cli_name);
while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client( %s ) message: %s",cli_name, recvbuf);
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
send(connectfd,sendbuf,strlen(sendbuf),0);
}
close(connectfd); /* close connectfd */
}
void sig_handler(int s)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
return;
}
===========================
//FIFO 服务器实例。其产生一个管道,用于接收客户发来的信息。将收到的字符串
转换为大写字母,再通过客户创建的管道发回到相应的客户。

#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define SERVER_FIFO_NAME "./serv_fifo"
#define CLIENT_FIFO_NAME "./cli_%d_fifo"
#define BUFFER_SIZE 20
struct data_to_pass_st {
pid_t client_pid;
char some_data[BUFFER_SIZE - 1];
};
int main()
{
int server_fifo_fd, client_fifo_fd;
struct data_to_pass_st my_data;
int read_res;
char client_fifo[256];
char *tmp_char_ptr;
mkfifo(SERVER_FIFO_NAME, 0777);
server_fifo_fd = open(SERVER_FIFO_NAME, O_RDONLY);
if (server_fifo_fd == -1) {
fprintf(stderr, "Server fifo failure\n");
exit(EXIT_FAILURE);
}
sleep(10); /* lets clients queue for demo purposes */
do {
read_res = read(server_fifo_fd, &my_data, sizeof(my_data));
if (read_res > 0) {
tmp_char_ptr = my_data.some_data;
while (*tmp_char_ptr) {
*tmp_char_ptr = toupper(*tmp_char_ptr);
tmp_char_ptr++;
}
sprintf(client_fifo, CLIENT_FIFO_NAME, my_data.client_pid);
client_fifo_fd = open(client_fifo, O_WRONLY);
if (client_fifo_fd != -1) {
write(client_fifo_fd, &my_data, sizeof(my_data));
close(client_fifo_fd);
}
}
} while (read_res > 0);
close(server_fifo_fd);
unlink(SERVER_FIFO_NAME);
exit(EXIT_SUCCESS);
}
======================================
// FIFO 客户实例。客户程序首先打开服务器管道,然后创建自己的管道,通过服务器
管道发送信息给服务器,并且通过自己创建的管道接收服务器发回的信息。

#include <ctype.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define SERVER_FIFO_NAME "./serv_fifo"
#define CLIENT_FIFO_NAME "./cli_%d_fifo"
#define BUFFER_SIZE 20
struct data_to_pass_st {
pid_t client_pid;
char some_data[BUFFER_SIZE - 1];
};
int main()
{
int server_fifo_fd, client_fifo_fd;
struct data_to_pass_st my_data;
int times_to_send;
char client_fifo[256];
server_fifo_fd = open(SERVER_FIFO_NAME, O_WRONLY);
if (server_fifo_fd == -1) {
fprintf(stderr, "Sorry, no server\n");
exit(EXIT_FAILURE);
}
my_data.client_pid = getpid();
sprintf(client_fifo, CLIENT_FIFO_NAME, my_data.client_pid);
if (mkfifo(client_fifo, 0777) == -1) {
fprintf(stderr, "Sorry, can't make %s\n", client_fifo);
exit(EXIT_FAILURE);
}
for (times_to_send = 0; times_to_send < 5; times_to_send++) {
sprintf(my_data.some_data, "Hello from %d", my_data.client_pid);
printf("%d sent %s, ", my_data.client_pid, my_data.some_data);
write(server_fifo_fd, &my_data, sizeof(my_data));
client_fifo_fd = open(client_fifo, O_RDONLY);
if (client_fifo_fd != -1) {
if (read(client_fifo_fd, &my_data, sizeof(my_data)) > 0) {
printf("received: %s\n", my_data.some_data);
}
close(client_fifo_fd);
}
}
close(server_fifo_fd);
unlink(client_fifo);
exit(EXIT_SUCCESS);
}

========================================
// 服务器异常处理实例。该程序对socket()调用异常采用终止程序的方法处理。对于accept()和send()调用异常而言,如果是EINTR 错误则重新调用该函数,否则终止
程序;对于recv()的调用异常,如果是EINTR 错误则重新调用该函数,如果是超时错误则终
止连接,显示超时信息并结束该进程。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
#define MAXDATASIZE 1000
void process_cli(int connectfd, sockaddr_in client), void sig_handler(int s);
int myrecv(int, char*, int,int), mysend(int,char*,int,int);
main()
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
struct sigaction act, oact;
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGCHLD, &act, &oact) < 0) {
perror("Sigaction failed!");
exit(1);
}
/* create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* Accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
if (errno == EINTR) continue;
perror("accept() error\n");
exit(1);
}
/* create child */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
int num;
char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) );
/* Get client's name from client */
num = myrecv(connectfd, cli_name, MAXDATASIZE,0);
if (num == 0) {
close(connectfd);
printf("Client disconnected.\n");
return;
}
cli_name[num - 1] = '\0';
printf("Client's name is %s.\n",cli_name);
while (num = myrecv(connectfd, recvbuf, MAXDATASIZE,0)) {
recvbuf[num] = '\0';
printf("Received client( %s ) message: %s",cli_name, recvbuf);
for (int i = 0; i < num - 1; i++) {
sendbuf[i] = recvbuf[num - i -2];
}
sendbuf[num - 1] = '\0';
mysend(connectfd,sendbuf,strlen(sendbuf),0);
}
close(connectfd); /* close connectfd */
}
void sig_handler(int s)
{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
return;
}
#define TIMEOUT 120
int myrecv(int connfd, char* buf, int len ,int flag)
{
int num;
fd_set fdRSet;
struct timeval timeout;
int maxfd = connfd + 1;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO(&fdRSet);
FD_SET(connfd, &fdRSet);
switch (select(maxfd, &fdRSet,NULL, &timeout)) {
case -1: perror();
close(connfd);
exit(1);
case 0: printf("Receiving timeout.\n");
close(connfd);
exit(1);
default: while ((num = recv(connfd, buf, len, flag)) == -1) {
if (errno == EINTR) continue;
perror();
close(connfd);
exit(1);
}
break;
}
return num;
}
int mysend(int connfd, char* buf, int len, int flag)
{
int num;
while ((num = send(connfd, buf, len, flag)) == -1) {
if (errno == EINTR) continue;
perror();
close(connfd);
exit(1);
}
return num;
}
============================================================

//守护进程实例。该程序实现以守护进程方式运行的聊天室服务器。

#include <stdio.h>
#include <string.h>
#include <vector.h>
#include "pthread.h"
#include <syslog.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include "Mysocket.h"
#include "MyThread.h"
#include "MySync.h"
#include "TcpServThr.h"
#include "Chat.h"
class ChatServerd : public ChatServer
{
int MsgPriority;
void closeall(int fd);
public:
ChatServerd(int port, char *hostname = NULL);
ChatServerd(int port, int max_conn, int maxusr, int len, char *hostname);
int daemon(char* name,int facility = 0);
void DealRecv(MyThread* thread);
void DealSend(MyThread* thread);
void SetPriority(int p) {MsgPriority = p;}
int GetPriority() {return MsgPriority;}
};
ChatServerd::ChatServerd(int port, char *hostname):
ChatServer(port,hostname)
{
MsgPriority = LOG_NOTICE|LOG_LOCAL0;
}
ChatServerd::ChatServerd(int port, int max_conn, int maxusr, int len, char *hostname):
ChatServer(port,max_conn, maxusr, len, hostname)
{
MsgPriority = LOG_NOTICE|LOG_LOCAL0;
}
void ChatServerd::DealRecv(MyThread* thread)
{
syslog(MsgPriority,"Receiver is running!\n");
char buf[MAX_PACKET_LEN];
int socket = ((Receiver*) thread)->socket;
int len = recv(socket,buf,MAX_NAME_LEN,0);
buf[len - 1] = ':';
buf[len] = '\0';
syslog(MsgPriority,"%s %d\n",buf,len);
while (1) {
int len1 = recv(socket,buf + len,MAX_PACKET_LEN,0);
if (len1 < 1) break;
buf[len1 + len] = '\0';
syslog(MsgPriority,"Recv:%s",buf);
msg->Add(socket, buf);
con->wakeAll();
}
DelThread(thread);
}
void ChatServerd::DealSend(MyThread* thread)
{
char buf[MAX_PACKET_LEN];
long maxsn;
maxsn = msg->GetSN() - 1;
int socket = ((Receiver*) thread)->socket;
syslog(MsgPriority,"Sender is running!\n");
while(1) {
con->wait();
int err = msg->Get(socket,&maxsn,buf);
if (err) continue;
syslog(MsgPriority,"Send:%s",buf);
Send(socket,buf,strlen(buf),0);
}
DelThread(thread);
}
int ChatServerd::daemon(char* name,int facility)
{
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0); // exit the original process
}
if (setsid() < 0)
return -1;
signal(SIGHUP,SIG_IGN); // ignore SIGHUP
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0);
}
chdir("/");
closeall(0);
open("/dev/null",O_RDWR);
dup(0);
dup(0);
openlog(name,LOG_PID,facility);
return 0;
}
void ChatServerd::closeall(int fd)
{
int fdlimit = sysconf(_SC_OPEN_MAX);
while (fd < fdlimit)
{
if (fd != Mysocket) close(fd);
fd++;
}
}
/*************************************************************/
int main(int argc, char** argv)
{
FILE* file = fopen("chatd.conf","r");
if (file == NULL) {
perror("chatd.conf:");
exit(1);
}
char input[100];
int port = 1234;
int max_conn = 20;
int maxusr = 20;
int len = 20;
char *hostname = "127.0.0.1";
while(1) {
char* s = fgets(input,100,file);
if (s == NULL) break;
if (!strncasecmp(input,"PORT",4)) port = atoi(strrchr(input,' '));
if (!strncasecmp(input,"MAX_USRS",8)) maxusr = atoi(strrchr(input,' '));
if (!strncasecmp(input,"QUELEN",6)) len = atoi(strrchr(input,' '));
if (!strncasecmp(input,"MAX_CONN",8)) max_conn = atoi(strrchr(input,' '));
if (!strncasecmp(input,"HOSTNAME",8)) hostname = strrchr(input,' ');
}
ChatServerd chatd(port, max_conn,maxusr, len, hostname);
if (chatd.daemon(argv[0]) < 0) {
perror("daemon");
exit(2);
}
chatd.Init();
chatd.Run();
return 0;
}
========================================================
// 原始套接字实例。其实现一个简单的ping 程序。

#include <iostream.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h> /* inet_ntoa */
#include <unistd.h> /* close */
#include <stdio.h> /* Basic I/O routines */
#include <sys/types.h> /* standard system types */
#include <netinet/in.h> /* Internet address structures */
#include <sys/socket.h> /* socket interface functions */
#include <netdb.h> /* host to IP resolution */
#include <netinet/in_systm.h>
#include <netinet/ip.h> /* ICMP */
#include <netinet/ip_icmp.h> /* ICMP */
#define ICMPHEAD 8 // ICMP packet header's length
#define MAXICMPLEN 200
/****************
class: RawSock
******************/
class RawSock
{
public:
int sock;
int error;
RawSock(int protocol =0);
virtual ~RawSock();
int send(const void* msg, int msglen,sockaddr* addr,unsigned int len);
int send(const void* msg, int msglen,char* addr);
int receive(void* buf,int buflen,sockaddr* from,int* len);
int Error() {return error;}
};
class ICMP: public RawSock
{
public:
struct icmp *packet;
int max_len;
int length;
ushort_t checksum(ushort_t *addr,int len);
ICMP();
ICMP(int len);
~ICMP();
int send_icmp(char *to, void* buf,int len);
int recv_icmp(sockaddr* from);
void setCode(int c) { packet->icmp_code = c;}
void setId(int i) { packet->icmp_id = i; }
void setSeq(int s) { packet->icmp_seq = s;}
void setType(int t) { packet->icmp_type = t;}
};
RawSock::RawSock(int protocol = 0) {
sock = socket(AF_INET, SOCK_RAW,protocol);
setuid(getuid());
if (sock == -1) error= 1;
else error = 0;
}
RawSock::~RawSock(){
close(sock);
}
int RawSock::send(const void* msg,int msglen,sockaddr* to, unsigned int len) {
if (error) return -1;
int length = sendto(sock,msg,msglen,0,(const sockaddr*)to,len);
if (length == -1) {
error = 2;
return -1;
}
return length;
}
int RawSock::send(const void* msg,int msglen,char* hostname) {
sockaddr_in sin; // Sock Internet address
if (error) return -1;
if(hostname) {
hostent *hostnm = gethostbyname(hostname);
if(hostnm == (struct hostent *) 0) {
return -1;
}
sin.sin_addr.s_addr = *((unsigned long *)hostnm->h_addr);
}
else
return -1;
sin.sin_family = AF_INET;
return send(msg,msglen,(sockaddr *)&sin, sizeof(sin));
}
int RawSock::receive(void* buf,int buflen,sockaddr* from,int* len)
{
if (error) return -1;
while (1) {
int length = recvfrom(sock,buf,buflen,0,from,len);
if (length == -1)
if (errno == EINTR) continue;
else {
error = 3;
return -1;
}
return length;
}
}
/****************
class: ICMP
******************/
ICMP::ICMP(): RawSock(IPPROTO_ICMP)
{
max_len = MAXICMPLEN;
packet = (icmp*) new char[max_len];
packet->icmp_code = 0;
packet->icmp_id = 0;
packet->icmp_seq = 0;
packet->icmp_type = ICMP_ECHO;
}
ICMP::ICMP(int len): RawSock(IPPROTO_ICMP)
{
max_len = len;
packet = (icmp*) new char[max_len];
packet->icmp_code = 0;
packet->icmp_id = 0;
packet->icmp_seq = 0;
packet->icmp_type = ICMP_ECHO;
}
ICMP::~ICMP()
{
delete[] (char*) packet;
}
ushort_t ICMP::checksum(ushort_t *addr,int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while (nleft > 1) {
sum+=*w++;
nleft -= 2;
}
if (nleft == 1) {
*(unsigned char*) (&answer) = *(unsigned char*) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum>>16);
answer = ~sum;
return (answer);
}
int ICMP::send_icmp(char *host, void* buf,int len)
{
memcpy(packet->icmp_data,buf,len);
packet->icmp_cksum = 0;
packet->icmp_cksum = checksum((unsigned short *)packet, ICMPHEAD + 6);
int err = send(packet,MAXICMPLEN,host);
return err;
}
int ICMP::recv_icmp(sockaddr* from)
{
char buf[MAXICMPLEN + 100];
int hlen1, icmplen;
struct ip *ip;
struct icmp *icmp;
if (Error()) return -1;
int addrlen = 0;
int len = receive(buf,MAXICMPLEN+100,from,&addrlen);
if (len == -1) {
cout << "Receiving Failed!\n" ;
return -1;
}
ip = (struct ip *) buf; /* start of IP header */
hlen1 = ip->ip_hl << 2; /* length of IP header */
icmp = (struct icmp *) (buf + hlen1); /* start of ICMP header */
if ( (icmplen = len - hlen1) < 8){
cout << "Receiving Failed!\n" ;
return -1;
}
length = len - hlen1;
memcpy(packet,icmp,length);
return 0;
}
main(int argc, char *argv[])
{
ICMP icmp;
sockaddr from;
char *host;
int count;
if (argc < 2) {
printf("Usage: %s <IP Address> <try_number>\n",argv[0]);
exit(1);
}
if (argc == 2) {
host = argv[1];
count = 5;
}
if (argc == 3) {
host = argv[1];
count = atoi(argv[2]);
}
for (int i = 0; i <= count; i++) {
icmp.setId(getpid());
icmp.setSeq(i);
char* test_data= "abcde";
icmp.send_icmp(host,test_data,strlen(test_data));
}
int num = 1;
while(1) {
if (icmp.recv_icmp(&from) < 0) continue;
if (icmp.packet->icmp_type == ICMP_ECHOREPLY) {
if (icmp.packet->icmp_id == getpid()) {
printf("%d bytes from %s: seq=%u, data=%s\n",
icmp.length, host,icmp.packet->icmp_seq, icmp.packet->icmp_data);
num ++;
if (num > count) break;
}
}
}
}

================================================
// 数据链路访问实例。该程序实现捕获所需的包并显示。
 
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFSIZ 1000
#define PCAP_ERRBUF_SIZE 200
void Display( const u_char * packet, const size_t length );
/* list all packets be filtered */
void my_callback ( u_char * none, const struct pcap_pkthdr * pkthdr, const u_char * packet )
{
Display( ( u_char * )packet, ( size_t )( pkthdr->caplen ) );
return;
}
int main(int argc,char **argv)
{
int i;
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* descr;
const u_char *packet;
struct pcap_pkthdr hdr;
struct ether_header *eptr;
struct bpf_program fp;
bpf_u_int32 maskp;
bpf_u_int32 netp;
if(argc != 2){
fprintf(stdout,"Usage: %s \"filter program\"\n" ,argv[0]);
return 0;
}
/* grab a device */
dev = pcap_lookupdev(errbuf);
if(dev == NULL) {
fprintf(stderr,"%s\n",errbuf);
exit(1);
}
/* ask pcap for the network address and mask of the device */
pcap_lookupnet(dev,&netp,&maskp,errbuf);
/* open device for reading this time lets set it in promiscuous
* mode so we can monitor traffic to another machine */
descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
if(descr == NULL) {
printf("pcap_open_live(): %s\n",errbuf);
exit(1);
}
/* Lets try and compile the program.. non-optimized */
if(pcap_compile(descr,&fp,argv[1],0,netp) == -1) {
fprintf(stderr,"Error calling pcap_compile\n");
exit(1);
}
/* set the compiled program as the filter */
if(pcap_setfilter(descr,&fp) == -1) {
fprintf(stderr,"Error setting filter\n");
exit(1);
}
/* capture packets */
pcap_loop(descr,-1,my_callback,NULL);
return 0;
}
void Display ( const u_char * packet, const size_t length )
{
u_long offset;
int i, j, k;
printf( "packet [ %lu bytes ]: \n", ( long unsigned int )length );
if ( length <= 0 ) {
return;
}
i = 0;
offset = 0;
for ( k = length / 16; k > 0; k--, offset += 16 ){
printf( "%08X ", ( unsigned int )offset );
for ( j = 0; j < 16; j++, i++ ) {
if ( j == 8 ){
printf( "-%02X", packet[i] );
}
else printf( " %02X", packet[i] );
}
printf( " " );
i -= 16;
for ( j = 0; j < 16; j++, i++ ) {
/* if ( isprint( (int)packet[i] ) ) */
if ( ( packet[i] >= ' ' ) && ( packet[i] <= 255 ) ) {
printf( "%c", packet[i] );
}
else printf( "." );
}
printf( "\n" );
}
k = length - i;
if ( k <= 0 ){
return;
}
printf( "%08X ", ( unsigned int )offset );
for ( j = 0 ; j < k; j++, i++ ){
if ( j == 8 ){
printf( "-%02X", packet[i] );
}
else printf( " %02X", packet[i] );
}
i -= k;
for ( j = 16 - k; j > 0; j-- ) {
printf( " " );
}
printf( " " );
for ( j = 0; j < k; j++, i++ ){
if ( ( packet[i] >= ' ' ) && ( packet[i] <= 255 ) ) {
printf( "%c", packet[i] );
}
else {
printf( "." );
}
}
printf( "\n" );
return;
}

==========================================
//单个服务器绑定到多个接口实例。该程序绑定于所有IP 地址上且端口号为1234,当与客户建立连接后显示被连接的IP 地址及端口号。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
void process_cli(int connectfd, sockaddr_in client);
main()
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
/* creaet TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* create child process */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
sockaddr_in address;
int namelen;
getsockname(connectfd, (sockaddr *)&address, &namelen);
printf("Connected to address ( %s )\n ",inet_ntoa(address.sin_addr) );
close(connectfd); /* close connectfd */
}
===========================================================================
 
//多个服务器绑定到多个接口实例。该程序通过命令行参数获得该服务器所绑定的地址,服务器完成地址绑定后侦听客户连接并服务客户。

#include <stdio.h> /* These are the usual header files */
#include <strings.h> /* for bzero() */
#include <unistd.h> /* for close() */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* Port that will be opened */
#define BACKLOG 2 /* Number of allowed connections */
void process_cli(int connectfd, sockaddr_in client);
main(int argc, char* argv[])
{
int listenfd, connectfd; /* socket descriptors */
pid_t pid;
struct sockaddr_in server; /* server's address information */
struct sockaddr_in client; /* client's address information */
int sin_size;
if (argc !=2) {
printf("Usage: %s <IP Address>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL){ /* calls gethostbyname() */
printf("gethostbyname() error\n");
exit(1);
}
/* Create TCP socket */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* handle exception */
perror("Creating socket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr = *((struct in_addr *)he->h_addr);
if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {
/* handle exception */
perror("Bind error.");
exit(1);
}
if(listen(listenfd,BACKLOG) == -1){ /* calls listen() */
perror("listen() error\n");
exit(1);
}
sin_size=sizeof(struct sockaddr_in);
while(1)
{
/* accept connection */
if ((connectfd = accept(listenfd,(struct sockaddr *)&client,&sin_size))==-1) {
perror("accept() error\n");
exit(1);
}
/* create child process */
if ((pid=fork())>0) {
/* parent process */
close(connectfd);
continue;
}
else if (pid==0) {
/* child process */
close(listenfd);
process_cli(connectfd, client);
exit(0);
}
else {
printf("fork error\n");
exit(0);
}
}
close(listenfd); /* close listenfd */
}
void process_cli(int connectfd, sockaddr_in client)
{
sockaddr_in address;
int namelen;
getsockname(connectfd, (sockaddr *)&address, &namelen);
printf("Connected to address ( %s )\n ",inet_ntoa(address.sin_addr) );
close(connectfd); /* close connectfd */
}
==================================================================
//路由套接字实例。该程序从命令行参数读入目的地址,创建路由套接字,发送RTM-GET 消息给系统核,然后通过路由套接字读取返回的路由信息并显示。
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/route.h>
#include <sys/param.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void cp_rtaddrs(int, sockaddr_in *, sockaddr_in **);
#define BUFLEN (sizeof(rt_msghdr) + 512)
#define SEQ 1234
int main(int argc, char **argv)
{
int sockfd;
char *buf;
pid_t pid;
ssize_t n;
struct rt_msghdr *rtm;
struct sockaddr_in *sa, *rt_info[RTA_NUMBITS];
struct sockaddr_in *sin;
if (argc != 2) {
printf("usage: %s <IPaddress>\n", argv[0]);
exit(0);
}
sockfd = socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */
if (sockfd == -1) {
perror("socket: ");
exit(1);
}
buf = (char * ) calloc(1, BUFLEN); /* and initialized to 0 */
rtm = (rt_msghdr *) buf;
rtm->rtm_msglen = sizeof(rt_msghdr) + sizeof(sockaddr_in);
rtm->rtm_version = RTM_VERSION;
rtm->rtm_type = RTM_GET;
rtm->rtm_addrs = RTA_DST;
rtm->rtm_pid = pid = getpid();
rtm->rtm_seq = SEQ;
sin = (sockaddr_in *) (rtm + 1);
sin->sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &sin->sin_addr);
write(sockfd, rtm, rtm->rtm_msglen);
do {
n = read(sockfd, rtm, BUFLEN);
} while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ || rtm->rtm_pid != pid);
sa = (sockaddr_in *) (rtm + 1);
cp_rtaddrs(rtm->rtm_addrs, sa, rt_info);
if ( (sa = rt_info[RTA_DST]) != NULL)
printf("dest: %s\n", inet_ntoa(sa->sin_addr));
if ( (sa = rt_info[RTA_GATEWAY]) != NULL)
printf("gateway: %s\n", inet_ntoa(sa->sin_addr));
if ( (sa = rt_info[RTA_NETMASK]) != NULL)
printf("netmask: %s\n", inet_ntoa(sa->sin_addr));
exit(0);
}
void cp_rtaddrs(int addrs, struct sockaddr_in *sa, struct sockaddr_in **rt_info)
{
int i;
for (i = 0; i < RTA_NUMBITS; i++) {
if (addrs & (1 << i)) {
rt_info[i] = sa;
sa++;
} else
rt_info[i] = NULL;
}
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值