幾行代碼教你入門套接字編程

套接字是網絡通信的基礎,特別是C/C++編程中隨處可見,所以不得不知,不得不學。

那麼什麼是套接字?請參考另一篇文章:

https://blog.csdn.net/fengxianghui01/article/details/104398214

在這一篇文章中就只討論怎樣創建套接字並實現通信。既然是通信,那肯定是雙方的,所以一般稱通信的雙方爲“服務端”和“客戶端”。顧名思義,“服務端”是提供服務的一段,“客戶端”是訪問的一段。其實就是通信的兩端,不要去糾結兩端誰是誰。兩者不只是名字上的區別,在創建套接字的時候也區別。創建流程爲:

服務端:創建套接字的流程(創建->綁定->監聽->連接)

客戶端:創建套接字的流程(創建->連接)

點對點的單一通信方式。下面貼代碼,直接點:

// 服務端

// server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>

#define PORT 5000

int sockfd;

void init_sock_communication()
{
	int nbytes = 0;
	int flags;

	char buffer[1024];

	struct sockaddr_in server_addr;    
	
	/* 服務器端開始建立 socket 描述符 */
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr, "Socketerror:%s\n\a", strerror(errno));
		exit(1);
	}

	/* 服務器端填充 sockaddr 結構 */
	bzero(&server_addr, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	server_addr.sin_port = htons(PORT);

	/* 捆綁 sockfd 描述符 */
	if (bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr, "Binderror:%s\n\a", strerror(errno));
		exit(1);
	}
	printf("Server Port : %d ... ...\n", PORT);

	/* 監聽 sockfd 描述符 */
	if (listen(sockfd, 2) == -1)
	{
		fprintf(stderr, "Listenerror:%s\n\a", strerror(errno));
		exit(1);
	}
	printf("create sock succeed!\n");
}

int main()
{
	int    sin_size, new_fd;
	struct sockaddr_in client_addr;	
	
	init_sock_communication();
	
	// 服務器阻塞,直到客戶程序建立連接
	sin_size = sizeof(struct sockaddr_in);
	while(1)
	{
		new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size);
		printf("receive new client connect!");
	}
	
}

// client.c

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

static char serverIP[32] = "192.168.216.130";
int sockfd;
#define TRUE 1
#define SUCCEED 1
#define FAILED 0

#define PORT 5000
int connect_server()
{
    struct hostent *host;
	struct sockaddr_in server_addr;
    uint8_t strhost[32];
	int iLoop = 5;

	snprintf(strhost, 32, "%s", serverIP);
	if((host = gethostbyname(strhost)) == NULL)
	{
	    fprintf(stderr, "Get host name error\n");
		exit(1);
	}

	printf("Ready to connect server ... ...\n");
	
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr = *((struct in_addr *)host->h_addr);

	while(iLoop--)
	{
	    if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == 0)
	    {
	        iLoop = 5;
			printf("connect server succeed! ... ...\n");
			return SUCCEED;
	    }
		
		printf("reconnect the server , %d ... ...\n", iLoop);
		sleep(1);
	}
	printf("connect the server failed, Error Message : [%s]\n", strerror(errno));
	return FAILED;
}


int main(int argc, char *argv[])
{	
    int running = 1;
	
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr, "create socket error : %s\n!", strerror(errno));
		exit(1);
	}
	
	//連接服務器/初始化接收消息線程/客戶端工作線程初始化 
	if(connect_server())	
	{
		close(sockfd);
		exit(1);
	}
}

編譯執行後:

cient:

Ready to connect server ... ...
connect server succeed! ... ...

就這麼簡單,創建了一個TCP套接字。當然UDP套接字更簡單。

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