socket网络编程

  1. 客户端为什么不需要bind?
    因为服务器是时时在监听有没有客户端的连接,所以需要绑定IP和端口。而客户端就不需要了,客户端上线是主动向服务器发出请求的,因为服务器已经绑定了IP和端口,所以客户端上线的就向这个IP和端口发出请求,客户端的端口是系统随机分配的。bind()函数和connect()的参数列表很相似,但是第二个参数,bind()的参数为struct sockaddr *my_addr,即为服务端本地的地址,而connect()的第二个参数为struct sockaddr *serv_addr,即为服务器端的地址,所以客户端可以直接向目标服务器发起请求,而目标服务器只需要bind后监听客户端的请求即可。

server.c守护进程

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <netinet/in.h>
#include <arpa/inet.h> 
#include <netdb.h>
#include <sys/socket.h>
#include <pthread.h>
#include <semaphore.h>
#include <syslog.h>

#define PORT			4321
#define BUFFER_SIZE		10240
#define MAX_QUE_CONN_NM	5
#define MAX_MSG         128

struct Param{
	int src_sock, dest_sock, thread_id;
};
pthread_t thread[2];
void *forward(void *arg){
	struct Param tmp = *(struct Param*)arg;
	char str[MAX_MSG];
	int res;
	while(1){
		res = read(tmp.src_sock, str, MAX_MSG);
		if(res == -1){
			syslog(LOG_ERR, "read error");
			exit(1);
			// pthread_exit(NULL);
		}
		res = write(tmp.dest_sock, str, MAX_MSG);		
		if(res == -1){
			syslog(LOG_ERR, "write error");
			exit(1);
			// pthread_exit(NULL);
		}
		if(strcmp(str, "quit") == 0){
			pthread_cancel(thread[tmp.thread_id ^ 1]);
			pthread_exit(NULL);
		}
	}
	pthread_exit(NULL);
}

void work(){
    int serv_sock = socket(AF_INET, SOCK_STREAM, 0);

	if(serv_sock == -1){
		syslog(LOG_ERR, "%s\n", "socket"); 
		exit(1); 
	}
	
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    // serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
	serv_addr.sin_addr.s_addr = INADDR_ANY;
	
    int res = bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(res == -1){
		syslog(LOG_ERR, "%s\n", "bind"); 
		exit(1); 
	}

    res = listen(serv_sock, MAX_QUE_CONN_NM);
	
	if(res == -1){
		syslog(LOG_ERR, "%s\n", "listen"); 
		exit(1); 
	}
	while(1){
		struct sockaddr_in clnt_addr1, clnt_addr2;    											 
		socklen_t clnt_addr_size1 = sizeof(clnt_addr1), clnt_addr_size2 = sizeof(clnt_addr2);   
		int clnt_sock1 = accept(serv_sock, (struct sockaddr*)&clnt_addr1, &clnt_addr_size1);
		if(clnt_sock1 == -1){
			syslog(LOG_ERR, "%s\n", "accept1"); 
			exit(1); 
		}
		int clnt_sock2 = accept(serv_sock, (struct sockaddr*)&clnt_addr2, &clnt_addr_size2);
		if(clnt_sock2 == -1){
			syslog(LOG_ERR, "%s\n", "accept2"); 
			exit(1); 
		}
		
		struct Param arg1, arg2;
		arg1.src_sock = clnt_sock1;
		arg1.dest_sock = clnt_sock2;
		arg1.thread_id = 0;
		arg2.src_sock = clnt_sock2;
		arg2.dest_sock = clnt_sock1;
		arg2.thread_id = 1;
		res = pthread_create(&thread[0], NULL, forward, &arg1);
		if(res != 0){
			syslog(LOG_ERR, "thread create failed, ERROR NUMBER:%d\n", res); 
			exit(1); 
		}
		res = pthread_create(&thread[1], NULL, forward, &arg2);
		if(res != 0){
			syslog(LOG_ERR, "thread create failed, ERROR NUMBER:%d\n", res); 
			exit(1); 
		}
		
		void * thrd_ret;
		res = pthread_join(thread[0], &thrd_ret);
		if(res != 0){
			syslog(LOG_ERR, "thread join failed, ERROR NUMBER:%d\n", res); 
			exit(1); 
		}
		res = pthread_join(thread[1], &thrd_ret);
		if(res != 0){
			syslog(LOG_ERR, "thread join failed, ERROR NUMBER:%d\n", res); 
			exit(1); 
		}
		close(clnt_sock1);
		close(clnt_sock2);
	}
	close(serv_sock);
}

int main(){
	pid_t pid, sid; 
	int i, fd; 
	pid = fork();
	if (pid < 0){ 
		printf("Error fork\n"); 
		exit(1); 
	} 
	else if (pid > 0){ 
		exit(0);
	} 
	openlog("daemon_syslog", LOG_PID, LOG_DAEMON);
	if(sid = setsid() < 0){
		syslog(LOG_ERR, "%s\n", "setsid"); 
		exit(1); 
	}
	if(sid = chdir("/") < 0){
		syslog(LOG_ERR, "%s\n", "chdir"); 
		exit(1); 
	}
	umask(0);
	for(i = 0; i < getdtablesize(); i++){ //getdtablesize()返回所在进程的文件描述符表的项数
		close(i); 
	} 
	/**** do something ****/
	
	work();
	
	/***********************/
	closelog();
	exit(0); 
} 

client.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <semaphore.h>

#define PORT			4321
#define MAX_MSG         128
#define BUFFER_SIZE		1024

struct Param{
	int sock;
};
pthread_t send_thread, recv_thread;

void *send_func(void *arg){
	struct Param tmp = *(struct Param*)arg;
	char buf[BUFFER_SIZE];
	while(1){
		memset(buf, 0, MAX_MSG);
		printf("Please input(No more than 128 bytes and input \"quit\" to quit):\n");
		gets(buf);
		int res = write(tmp.sock, buf, MAX_MSG);
		if(res == -1){
			// pthread_cancel(recv_thread);
			// pthread_exit(NULL);
			perror("send thread error");
			exit(1);
		}
		if(strcmp(buf, "quit") == 0){
			pthread_cancel(recv_thread);
			pthread_exit(NULL);
		}
	}
	pthread_exit(NULL);
}

void *recv_func(void *arg){
	struct Param tmp = *(struct Param*)arg;
	char buf[BUFFER_SIZE];
	while(1){
		memset(buf, 0, MAX_MSG);
		int res = read(tmp.sock, buf, MAX_MSG);
		if(res == -1){
			// pthread_cancel(send_thread);
			perror("recv thread error");
			exit(1);
			// pthread_exit(NULL);
		}
		if(strcmp(buf, "quit") == 0){
			pthread_cancel(send_thread);
			pthread_exit(NULL);
		}
		puts("receive message:");
		puts(buf);
	}
	pthread_exit(NULL);
}

int main(){
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    //serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	serv_addr.sin_addr.s_addr = INADDR_ANY; //表示本机所有ip
	
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	
	
    int res;
	
	struct Param arg1, arg2;
	arg1.sock = sock;
	arg2.sock = sock;
	
	res = pthread_create(&send_thread, NULL, send_func, &arg1);
	if(res != 0){
		fprintf(stderr, "send thread create failed, ERROR NUMBER:%d", res);
		exit(1);
	}
	res = pthread_create(&recv_thread, NULL, recv_func, &arg2);
	if(res != 0){
		fprintf(stderr, "revc thread create failed, ERROR NUMBER:%d", res);
		exit(1);
	}
	void * thrd_ret;
	
	res = pthread_join(send_thread, &thrd_ret);
	if(!res){
		printf("send thread joined\n");
	}else{
		fprintf(stderr, "send thread join failed, ERROR NUMBER:%d", res);
		exit(1);
	}
	res = pthread_join(recv_thread, &thrd_ret);
	if(!res){
		printf("recv thread joined\n");
	}else{
                fprintf(stderr, "recv thread join failed, ERROR NUMBER:%d", res);
		exit(1);
	}
    close(sock);
    return 0;
}
posted @ 2021-05-23 13:26  Zeronera  阅读(147)  评论(0)    收藏  举报