/*******************************************************/
網絡基礎編程
/*******************************************************/
//common.h頭文件
#ifndef __COMMON_H__
#define __COMMON_H__ //定義頭文件common.h
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <error.h>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h> //包含的頭文件
#define Err_sys(info) / //定義錯誤處理函數
{ fprintf(stderr, "%s %s/n", info, strerror(errno)); /
exit(EXIT_FAILURE); /
}
#define addrsize sizeof(struct sockaddr_in) //套接字信息sockaddr_in結構體的大小
#define port 8888 //端口號
#define backlog 10
#define BUFFERSIZE 1024 //緩衝區大小
#define RUNNING 1 //運行狀態
#endif
/***********************************************************************/
服務器端:
#include "common.h"
int main (int argc, char *argv[])
{
int sockfd = -1, newfd = -1;
struct sockaddr_in server_addr, client_addr; //保存套接字結構信息服務器和客服端信息
socklen_t addrlen = addrsize;
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
int rc, wc;
sockfd = socket(PF_INET, SOCK_STREAM, 0); //建立socket連接
if(sockfd == -1)
Err_sys("Server socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
server_addr.sin_port = htons(port);
int i = 1; //允許重複使用本地地址與套接字進行綁定
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use
if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1) //綁定函數bind()
{
close(sockfd);
Err_sys("Server bind")
}
if(listen(sockfd, 10) == -1) //調用listen()函數,監聽,隊列中允許的最大請求數
{
close(sockfd);
Err_sys("Server listen")
}
bzero(&client_addr, addrsize);
printf("Waiting a new connection/n");
ee: newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen); //調用accept()函數,等待客服端的連接
if(newfd == -1)
{
if(errno == EINTR)
goto ee;
}
else
printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
memset(buffer_r, '/0', BUFFERSIZE);
while(RUNNING)
{
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(newfd, buffer_r, BUFFERSIZE, 0); //接收客服端發來的信息
if(rc <= 0)
{
if(rc == 0)
{
printf("Client has been closed/n");
}
close(newfd);
close(sockfd);
exit(EXIT_FAILURE);
}
else
printf("[Server recv]:%s/n", buffer_r);
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Server send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin);
wc = send(newfd, buffer_w, strlen(buffer_w), 0); //發送信息到客服端
if(wc < 0)
{
close(sockfd);
close(newfd);
Err_sys("Server send")
}
}//while
close(sockfd);
close(newfd);
exit(EXIT_SUCCESS);
}
/****************************************************************/
客戶端:
#include "common.h"
int main(int argc, char **argv)
{
int sockfd = -1;
struct sockaddr_in server_addr; //定義套接字結構體保持socket信息
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE]; //定義讀緩衝和寫緩衝
socklen_t addrlen = addrsize; //設置結構體大小
int wc, rc;
if(argc != 5)
{
fprintf(stderr, "%s -p port -i ip/n", argv[0]);
exit(EXIT_FAILURE);
}
sockfd = socket(PF_INET, SOCK_STREAM, 0); //建立socket連接
if(sockfd == -1)
Err_sys("Client socket")
bzero(&server_addr, addrsize); //設置sockaddr_in結構體中相關參數
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[4]);
server_addr.sin_port = htons(atoi(argv[2]));
int count = 0; //調用connect()函數主動發起對服務器端的連接
while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
if(count++ <= 3) //連接成功
{
fprintf(stderr, "Client is trying to connect.../n");
sleep(3);
}
else //連接失敗
{
fprintf(stderr, "Client connects failurefully/n");
close(sockfd); //shutdown(sockfd, SHUT_RDWR);
exit(EXIT_FAILURE);
}
}
while(RUNNING) //運行時
{
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Client send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin); //獲取標準輸入的內容 存到緩衝區
wc = send(sockfd, buffer_w, strlen(buffer_w), 0); //發送消息給服務器端
if(wc < 0)
Err_sys("Client send")
//printf("111111111111111111111/n");
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(sockfd, buffer_r, BUFFERSIZE, 0); //收到服務器發來的消息
if(rc <= 0)
{
if(rc == 0)
{
printf("Server has been closed/n");
}
close(sockfd);
exit(EXIT_FAILURE);
}
else
printf("[Client recv]:%s/n", buffer_r);
}//while
close(sockfd);
exit(EXIT_SUCCESS);
}
/***********************************************************************/
服務器端2:
#include "common.h"
int main (int argc, char *argv[])
{
int sockfd = -1, newfd = -1;
struct sockaddr_in server_addr, client_addr;
socklen_t addrlen = addrsize;
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
int rc, wc;
int i = 1;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
Err_sys("Server socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
server_addr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
close(sockfd);
Err_sys("Server bind")
}
if(listen(sockfd, 10) == -1)
{
close(sockfd);
Err_sys("Server listen")
}
bzero(&client_addr, addrsize);
printf("Waiting a new connection/n");
ee: newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
if(newfd == -1)
{
if(errno == EINTR)
goto ee;
}
else
printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(newfd, buffer_r, BUFFERSIZE, 0);
if(rc <= 0)
{
if(rc == 0)
{
printf("Client has been closed/n");
}
close(newfd);
close(sockfd);
exit(EXIT_FAILURE);
}
else
printf("[Server recv]:%s/n", buffer_r);
close(sockfd);
close(newfd);
exit(EXIT_SUCCESS);
}
/************************************************************************/
客戶端2:
#include "common.h"
int main(int argc, char **argv)
{
int sockfd = -1;
struct sockaddr_in server_addr;
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
socklen_t addrlen = addrsize;
int wc, rc;
if(argc != 5)
{
fprintf(stderr, "%s -p port -i ip/n", argv[0]);
exit(EXIT_FAILURE);
}
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
Err_sys("Client socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[4]);
server_addr.sin_port = htons(atoi(argv[2]));
int count = 0;
while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
if(count++ <= 3)
{
fprintf(stderr, "Client is trying to connect.../n");
sleep(3);
}
else
{
fprintf(stderr, "Client connects failurefully/n");
close(sockfd); //shutdown(sockfd, SHUT_RDWR);
exit(EXIT_FAILURE);
}
}
memset(buffer_w, '/0', BUFFERSIZE);
printf("Please input the sending message:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin);
wc = send(sockfd, buffer_w, strlen(buffer_w), 0);
if(wc < 0)
Err_sys("Client send")
exit(EXIT_SUCCESS);
}
/**************************************************************/
TCP多進程併發通信
/***************************************************************/
服務器端:
#include "common.h"
void sig_chld(int signo)
{
psignal(signo, "Catch signal");
int status;
while(wait(&status) == -1);
signal(SIGCHLD, sig_chld);
}
int main (int argc, char *argv[])
{
int sockfd = -1, newfd = -1;
struct sockaddr_in server_addr, client_addr;
socklen_t addrlen = addrsize;
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
int rc, wc;
pid_t pt;
fd_set readfds;
int maxfd;
struct timeval tv;
int ret = -1;
signal(SIGCHLD, sig_chld);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
Err_sys("Server socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
server_addr.sin_port = htons(port);
int i = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use
if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
close(sockfd);
Err_sys("Server bind")
}
if(listen(sockfd, 10) == -1)
{
close(sockfd);
Err_sys("Server listen")
}
while(RUNNING)
{
printf("Waiting a new connection/n");
newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
if(newfd == -1)
{
if(errno == EINTR)
continue;
Err_sys("Server accept")
}
else
printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
pt = fork(); //創建子進程
if(pt == -1)
{
close(newfd);
close(sockfd);
Err_sys("Fork")
}
else if(pt == 0) //child process
{
close(sockfd);
while(RUNNING)
{
maxfd = newfd;
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);//FD_SET(STDIN_FILENO, &readfds);
FD_SET(newfd, &readfds);
ret = select(maxfd + 1, &readfds, NULL, NULL, &tv);
switch(ret)
{
case -1:
if(errno == EINTR)
continue;
Err_sys("Server select")
case 0:
//printf("Server timeout/n");
continue;
default:
if(FD_ISSET(newfd, &readfds))
{
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(newfd, buffer_r, BUFFERSIZE, 0);
if(rc <= 0)
{
if(rc == 0)
{
FD_CLR(sockfd, &readfds);
printf("Client has been closed/n");
}
close(newfd);
close(sockfd);
exit(EXIT_FAILURE);
}
else
printf("[Server recv]:%s/n", buffer_r);
}//recv
if(FD_ISSET(0, &readfds))
{
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Server send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin);
wc = send(newfd, buffer_w, strlen(buffer_w), 0);
if(wc < 0)
{
close(sockfd);
close(newfd);
Err_sys("Server send")
}
}//send
}//switch
}//while read/write
} //else if(pt == 0)
else
close(newfd);
}//while accept
close(sockfd);
close(newfd);
exit(EXIT_SUCCESS);
}
/***********************************************************************/
客戶端:
#include "common.h"
int main(int argc, char **argv)
{
int sockfd = -1;
struct sockaddr_in server_addr;
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
socklen_t addrlen = addrsize;
int wc, rc;
int maxfd;
fd_set readfds;
int ret = -1;
struct timeval tv;
if(argc != 5)
{
fprintf(stderr, "%s -p port -i ip/n", argv[0]);
exit(EXIT_FAILURE);
}
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
Err_sys("Client socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[4]);
server_addr.sin_port = htons(atoi(argv[2]));
int count = 0;
while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
if(count++ <= 3)
{
fprintf(stderr, "Client is trying to connect.../n");
sleep(3);
}
else
{
fprintf(stderr, "Client connects failurefully/n");
close(sockfd); //shutdown(sockfd, SHUT_RDWR);
exit(EXIT_FAILURE);
}
}
while(RUNNING)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
maxfd = sockfd;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(sockfd, &readfds);
if((ret = select(maxfd + 1, &readfds, NULL, NULL, &tv)) == -1)
{
if(errno == EINTR)
continue;
close(sockfd);
Err_sys("Client select")
}
else if(ret == 0)
{
//printf("Client timeout");
continue;
}
else if(ret > 0)
{
if(FD_ISSET(0, &readfds))
{
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Client send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin);
wc = send(sockfd, buffer_w, strlen(buffer_w), 0);
if(wc < 0)
Err_sys("Client send")
}//send
if(FD_ISSET(sockfd, &readfds))
{
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(sockfd, buffer_r, BUFFERSIZE, 0);
if(rc <= 0)
{
if(rc == 0)
{
FD_CLR(sockfd, &readfds);
printf("Server has been closed/n");
}
close(sockfd);
exit(EXIT_FAILURE);
}
else
printf("[Client recv]:%s/n", buffer_r);
}//recv
}
}//while
close(sockfd);
exit(EXIT_SUCCESS);
}
/***************************************************************/
TCP多線程併發網絡編程
/***************************************************************/
服務器端:
#include "common.h"
/*Thread function for reading and writing*/
void *rdwrthread(void *arg)
{
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE];
int rc, wc;
int outfd = *(int *)arg;
fd_set readfds;
int maxfd;
struct timeval tv;
int ret = -1;
while(RUNNING)
{
maxfd = outfd;
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);//FD_SET(STDIN_FILENO, &readfds);
FD_SET(outfd, &readfds);
ret = select(maxfd + 1, &readfds, NULL, NULL, &tv);
switch(ret)
{
case -1:
if(errno == EINTR)
continue;
Err_sys("Server select")
case 0:
//printf("Server timeout/n");
continue;
default:
if(FD_ISSET(outfd, &readfds))
{
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(outfd, buffer_r, BUFFERSIZE, 0);
if(rc <= 0)
{
if(rc == 0)
{
FD_CLR(outfd, &readfds);
printf("Client has been closed/n");
}
close(outfd);
pthread_exit(NULL);
}
else
printf("[Server recv]:%s/n", buffer_r);
}//recv
if(FD_ISSET(0, &readfds))
{
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Server send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin);
wc = send(outfd, buffer_w, strlen(buffer_w), 0);
if(wc < 0)
{
close(outfd);
Err_sys("Server send")
}
}//send
}//switch
}//while read/write
return NULL;
}
int main (int argc, char *argv[])
{
int sockfd = -1, newfd = -1;
struct sockaddr_in server_addr, client_addr;
socklen_t addrlen = addrsize;
pthread_t pd;
pthread_attr_t attr;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
Err_sys("Server socket")
bzero(&server_addr, addrsize);
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //0.0.0.0
server_addr.sin_port = htons(port);
int i = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));//Server bind Address already in use
if(bind(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
close(sockfd);
Err_sys("Server bind")
}
if(listen(sockfd, 10) == -1)
{
close(sockfd);
Err_sys("Server listen")
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
while(RUNNING)
{
printf("Waiting a new connection/n");
newfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
if(newfd == -1)
{
if(errno == EINTR)
continue;
pthread_attr_destroy(&attr);
Err_sys("Server accept")
}
else
printf("Create a new connection ip[%s]::port[%d]/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if(pthread_create(&pd, &attr, rdwrthread, (void *)&newfd) != 0)
{
close(newfd);
close(sockfd);
pthread_attr_destroy(&attr);
Err_sys("Server pthread_create")
}
else
fprintf(stdout, "Current master thread[%u] creates a new slave thread[%u]/n", pthread_self(), pd);
}//while accept
close(sockfd);
close(newfd);
pthread_attr_destroy(&attr);
exit(EXIT_SUCCESS);
}
/****************************************************************/
客戶端:
#include "common.h"
int main(int argc, char **argv)
{
int sockfd = -1;
struct sockaddr_in server_addr; //定義套接字結構體保持socket信息
char buffer_r[BUFFERSIZE], buffer_w[BUFFERSIZE]; //定義讀緩衝和寫緩衝
socklen_t addrlen = addrsize; //設置結構體大小
int wc, rc;
int maxfd;
fd_set readfds; //讀文件描述符集
int ret = -1;
struct timeval tv; //時間結構體
if(argc != 5)
{
fprintf(stderr, "%s -p port -i ip/n", argv[0]);
exit(EXIT_FAILURE);
}
sockfd = socket(PF_INET, SOCK_STREAM, 0); //建立socket連接
if(sockfd == -1)
Err_sys("Client socket")
bzero(&server_addr, addrsize); //設置sockaddr_in結構體中相關參數
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[4]);
server_addr.sin_port = htons(atoi(argv[2]));
int count = 0; //調用connect()函數主動發起對服務器端的連接
while(connect(sockfd, (struct sockaddr *)&server_addr, addrsize) == -1)
{
if(count++ <= 3) //連接成功
{
fprintf(stderr, "Client is trying to connect.../n");
sleep(3);
}
else //連接失敗
{
fprintf(stderr, "Client connects failurefully/n");
close(sockfd); //shutdown(sockfd, SHUT_RDWR);
exit(EXIT_FAILURE);
}
}
while(RUNNING)
{
tv.tv_sec = 1; //設置多路複用超時時間1s
tv.tv_usec = 0;
maxfd = sockfd;
FD_ZERO(&readfds); //清除一個文件描述符集
FD_SET(0, &readfds); //將標準輸入加入到讀文件描述符集
FD_SET(sockfd, &readfds); //將套接字文件描述符加入到讀文件描述符集
if((ret = select(maxfd + 1, &readfds, NULL, NULL, &tv)) == -1) //判斷文件描述符在1s內是否變化
{
if(errno == EINTR) //遇到中斷的處理
continue;
close(sockfd);
Err_sys("Client select")
}
else if(ret == 0) //超時處理
{
//printf("Client timeout");
continue;
}
else if(ret > 0) //文件描述符集內有變化
{
if(FD_ISSET(0, &readfds)) //標準輸入文件描述符發生了變化
{
memset(buffer_w, '/0', BUFFERSIZE);
printf("[Client send]:");
fflush(stdout);
fgets(buffer_w, BUFFERSIZE, stdin); //獲取標準輸入的內容 存到緩衝區
wc = send(sockfd, buffer_w, strlen(buffer_w), 0); //發送消息給服務器端
if(wc < 0)
Err_sys("Client send")
}//send
if(FD_ISSET(sockfd, &readfds)) //sockfd文件描述符發生了變化
{
memset(buffer_r, '/0', BUFFERSIZE);
rc = recv(sockfd, buffer_r, BUFFERSIZE, 0); //收到服務器發來的消息
if(rc <= 0)
{
if(rc == 0)
{
FD_CLR(sockfd, &readfds); //將sockfd從文件描述符集中刪除
printf("Server has been closed/n");
}
close(sockfd); //關閉
exit(EXIT_FAILURE);
}
else
printf("[Client recv]:%s/n", buffer_r); //打印出內容
}//recv
}
}//while
close(sockfd); //關閉套接字
exit(EXIT_SUCCESS); //成功返回
}