03.5 基於socket的服務端客戶端通信

代碼如下:

服務端

#include <sys/socket.h>//sever
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <strings.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/tcp.h>

char host_name[20];
int port = 7777;

int main()
{
	struct sockaddr_in sin, pin;
	int sock_descriptor, temp_sock, address_size;
	int i, recvlen, on = 1;
	int nZero = 1;
	int leftlen = 0, sendlen = 0, retlen = 0;
	char buf[16384], sendbuf[1024] = {0}, *ptr = NULL;

	//通過socket(int domain,int type,int protocol)的函數原型創建AF_INIT協議族的流
	//類型的socket,當然type除了流socket的之外還有SOCKET_RAW,
	//據說這種類型的socket甚至可以僞裝數據包
	sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(sock_descriptor, SOL_SOCKET, SO_REUSEADDR, &nZero, sizeof(int));
	setsockopt(sock_descriptor, SOL_SOCKET, SO_REUSEPORT, &nZero, sizeof(int));
	setsockopt(sock_descriptor, IPPROTO_TCP, TCP_NODELAY, (char*)&nZero, sizeof(int));
	//int keepAlive = 1;
	//setsockopt(sock_descriptor, SOL_SOCKET, SO_KEEPALIVE,(void *)keepAlive, sizeof(keepAlive));

	bzero(&sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	//地址結構的端口地址,port是主機字節序,通過htons()進行字節序轉換成網絡字節序
	sin.sin_port = htons(port);
	//將sin的地址和socket文件描述符綁定到一起,綁定是數據接收和發//送的前提
	if (bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin)) == -1)
	{
		perror("call to bind");
		exit(1);
	}
	//監聽用來初始化服務器可連接隊列,因爲一次只能處理一個連接請求
	//當收到多個請求,將會存儲在隊列中,先到先得
	if (listen(sock_descriptor, 100) == -1)
	{
		perror("call to listen");
		exit(1);
	}
	printf("Accpting connections...\n");

	address_size = sizeof(pin);


	//接收客戶機,返回句柄
	temp_sock = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size);
	while (1)
	{
		//temp_sock = accept(sock_descriptor,(struct sockaddr *)&pin,&address_size);
		char buffer[1024] = { 0 };
		//句柄分辨不同客戶端
		printf("temp_sock=%d\n",temp_sock);
		//鏈接失敗
		if (temp_sock == -1)
		{
			perror("call to accept");
			exit(1);
		}
		//int recvlen = recv(temp_sock, buf,sizeof(buf),0);
		
		ptr = buffer;
		//收數據傳入buffer
		int recvlen = recv(temp_sock, ptr, 1024, 0);
		//斷開連接
		if (recvlen == -1)
		{
			perror("call to recv");
			exit(1);
		}
		else if (recvlen == 0)//無數據
		{
			printf("斷線重連...\n");
			temp_sock = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size);
			continue;
		}
		//send(tmp_sock, buffer, 1024, 0);
		//收到數據,打印
		printf("received msg: %s, size:%d\n", buffer, recvlen);
		//break;
	
		//send data
		retlen = 0;
		ptr = sendbuf;
		//	printf("sendlen1 = %d\n", sendlen);
		//while (leftlen) {
		//	printf("sendbuf1:%s\n", sendbuf);
			printf("sever_input:");
		//	gets(sendbuf);
			scanf("%s", &sendbuf);
		//	sprintf(sendbuf, "hello\n");
		//	printf("sendbuf2:%s\n", sendbuf);
		//	printf("sendlen2 = %d\n", sendlen);
			sendlen = strlen(sendbuf);
		//	printf("sendlen3 = %d\n", sendlen);
			//表示已經完成一次發送
			if (0 == leftlen) {
				leftlen = sendlen;
				printf("leftlen = sendlen;\n");
			}
			//退出標識符
			if (0 == strcmp(sendbuf, "quit")) {
				printf("quit...\n");
				break;
			}
			//發送
			printf("retlen1 = %d\n", retlen);
			//retlen = send(sock_descriptor, sendbuf, sendlen, 0);
			retlen = send(temp_sock, sendbuf, sendlen, 0);
			printf("retlen2 = %d\n", retlen);
			if (retlen < 0) {
				printf("retlen < 0\n");
				if (errno == EINTR)
					retlen = 0;
				else{
					printf("exit...");
					exit(1);
				}
			}
			else{
				printf("retlen3 = %d\n", retlen);
			}
			leftlen -= retlen;
		//}

	}

	close(temp_sock);
	close(sock_descriptor);
	return 0;
}

客戶端

#include <stdio.h>  
#include <string.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <syslog.h>  
#include <errno.h>  
#include <stdlib.h>  
#define MAX_LISTEN_NUM 5  
#define SEND_BUF_SIZE 100  
#define RECV_BUF_SIZE 100  
#define SERVER_PORT 7777 
char *	server_ip = "192.168.60.253";
int main()
{
	int sock_fd = 0;
	char recvbuf[RECV_BUF_SIZE] = { 0 };
	char sendbuf[SEND_BUF_SIZE] = { 0 };
	int recvlen = 0;
	int retlen = 0;
	int sendlen = 0;
	int leftlen = 0;
	char *ptr = NULL;  //指向緩衝區的指針 
	struct sockaddr_in ser_addr;

	//memset(&ser_addr, 0, sizeof(ser_addr));  
	bzero(&ser_addr, sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;  //地址族inet
									//inet_aton("192.168.60.253", (struct in_addr *)&ser_addr.sin_addr);  
	inet_pton(AF_INET, server_ip, &ser_addr.sin_addr);
	//將整型變量從主機字節順序轉變成網絡字節順序
	ser_addr.sin_port = htons(SERVER_PORT);
	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_fd < 0)
	{
		perror("connecting to socket\n");
		fprintf(stderr, "%s:%d, create socket failed", __FILE__, __LINE__);
		exit(1);
	}

	int nZero = 1;//套接口初始化 
	setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &nZero, sizeof(int));
	setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT, &nZero, sizeof(int));
	//if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)  
	if (connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -1)
	{
		fprintf(stderr, "%s:%d, connect socket failed", __FILE__, __LINE__);
		exit(1);
	}
	//	sprintf(sendbuf, "hello server\n");  

	//send data  
	//sendlen = strlen(sendbuf) +1;  
	retlen = 0;
	//leftlen = sendlen;  
	ptr = sendbuf;

	//while(leftlen){  //發送緩存數據   
	while (1) {  //發送緩存數據   
		printf("input message:");
		gets(sendbuf); //
					   //scanf("%s",sendbuf);
		sendlen = strlen(sendbuf);

		//說明一條消息已經發送完畢
		if (0 == leftlen)
		{
			leftlen = sendlen;
		}

		//退出條件
		if (0 == strcmp(sendbuf, "quit"))
		{
			printf("quit...\n");
			break;
		}

		//printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n", retlen, sock_fd, sendlen, leftlen);
		//retlen = send(sock_fd, ptr, sendlen, 0);  
		//		printf("sendbuf:%s\n",sendbuf);
		retlen = send(sock_fd, sendbuf, sendlen, 0);
		//printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n", retlen, sock_fd, sendlen, leftlen);
		if (retlen < 0)
		{
			printf("retlen < 0\n");
			if (errno == EINTR)  //判斷信號是否中斷 
				retlen = 0;
			else
				printf("exit...");
			exit(1);
		}
		leftlen -= retlen;
		//		printf("leftlen=%d\n",leftlen);
		//ptr += retlen;
		//		printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n",retlen,sock_fd,sendlen,leftlen);

		//receive data  
		recvlen = 0;  //重置
		retlen = 0;
		ptr = recvbuf;  //指針ptr->緩衝區函數
		leftlen = RECV_BUF_SIZE - 1;
		//do {
			retlen = recv(sock_fd, ptr, leftlen, 0);
			if (retlen < 0)
			{
				if (errno == EINTR)
					retlen = 0;
				else
					exit(1);
			}
			recvlen += retlen;
			leftlen -= retlen;
			ptr += retlen;
		//} while (recvlen && leftlen);
		printf("receive data is : %s", recvbuf);
		//     sprintf(sendbuf, "hello server/n"); 	
	}  //while(1)

	close(sock_fd);

}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章