網路套接字

風是甜的你是我的發表於2018-06-26

套接字使得客戶端和服務端的程式通訊要麼是面向連線的,要麼是面向無連線的。如果一臺計算機上的客戶端套接字使用某個地址訪問在另一臺計算機上的服務套接字,那麼在指定的套接字進行應答後,這兩臺計算機之間就可以進行資料交換了。

套接字:

每個TCP及UDP的協議頭都包含了源埠和目的埠,埠值指明瞭兩個互相獨立的TCP單元使用者。

埠號和IP地址合起來唯一的表示了Internet上的唯一的主機上的應用程式的套接字的位置。

本機地址是機器的IP地址,程式地址是要繫結的埠號。

資料包套接字使用UDP協議,因為UDP是面向資料包的,流套接字使用TCP協議,TCP協議是面向位元組流的。

UDP套接字:

建立套接字:socket()

繫結套接字:bind()

傳送訊息:sendto()  連線傳送

接收訊息:recefrom()  接收資料

標頭檔案:

 udp_server.c

udp_client.c

 

TCP套接字:

 

建立套接字:socket()

繫結套接字:bind()

監聽套接字:listen()

接收請求:accept()

連線:connect()

tcp_server.c

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
#include<unistd.h>
void serverIO(int sock)
{
		char buf[1024];
		while(1)
		{
			ssize_t s = read(sock,buf,sizeof(buf)-1);
			if(s>0)
			{
				buf[s] = 0;
				printf("client: %s\n",buf);
				write(sock,buf,strlen(buf));
			}
			else if (s==0)
			{
				printf("quit\n");
				break;
			}
			else
			{
				perror("read");
				break;
			}
		}
		close(sock);
}
int main(int argc,char* argv[])
{
	if(argc!=3)
	{
		printf("Usage %s [ip] [port]\n",argv[0]);
		return 1;
	}

	int sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock<0)
	{
		perror("socket");
		return 2;
	}

	printf("sock:%d\n",sock);
	struct sockaddr_in server_socket;
	server_socket.sin_family = AF_INET;
	server_socket.sin_addr.s_addr = inet_addr( argv[1]);
	server_socket.sin_port = htons(atoi(argv[2]));

	//繫結埠
	if(bind(sock,(struct sockaddr*)&server_socket,sizeof(server_socket))<0)
	{
		perror("bind");
		return 3;
	}
	//由於這是TCP協議,所以是可靠傳輸,那麼這裡需要監聽對方是否已連線

	if(listen(sock,5)<0)
	{
		perror("listen");
		return 4;
	}

	while(1)
	{
		struct sockaddr_in client_socket;
		socklen_t len=sizeof(client_socket);
		//作為伺服器,需要先接收再傳送,接收來自客戶端的訊息
		int new_sock = accept(sock,(struct sockaddr*)&client_socket,&len);
		if(new_sock<0)
		{
			//printf("accept error\n");
			perror("accept");
			//return 5;
			continue;
		}

		//char buf_ip[INET_ADDRSTRLEN];
		//inet_ntop(AF_INET,&client_socket.sin_addr,buf_ip,sizeof(buf_ip));
		printf("get new connect,[ip] :%s [port]: %d\n",inet_ntoa(client_socket.sin_addr)\
					,ntohs(client_socket.sin_port));

		//chuangjianjincheng

		pid_t id = fork();
		if(id==0)
		{
			//child
			close(sock);
			if(fork()>0)
			{
				exit(1);
			}
			serverIO(new_sock);
			exit(0);
		}
		else
		{
			//father
			close(new_sock);//must close
			waitpid(id,NULL,0);
		}
	}
	return 0;
}

tcp_client.c

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
#include<unistd.h>

int main(int argc,char* argv[])
{
	if(argc!=3)
	{
		printf("Usage %s [ip] [port]\n",argv[0]);
		return 1;
	}

	int sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock<0)
	{
		perror("socket");
		return 2;
	}

	struct sockaddr_in server_socket;
	server_socket.sin_family = AF_INET;
	server_socket.sin_addr.s_addr = inet_addr( argv[1]);
	server_socket.sin_port = htons(atoi(argv[2]));

	if(connect(sock,(struct sockaddr*)&server_socket,sizeof(server_socket))<0)
	{
		perror("connect");
		return 3;
	}
	printf("connect success\n");

	while(1)
	{
		char buf[1024];
		printf("client# ");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1] = '\0';
		write(sock,buf,sizeof(buf));

		read(sock,buf,sizeof(buf));
		printf("server# %s\n",buf);
	}
	close(sock);
	return 0;
}

 

TCP  VS  UDP

 

TCP:面向連線,面向位元組流,可靠傳輸

UDP:面向無連線,面向資料包,不可靠傳輸

netstat:檢視網路狀態的工具

-n:拒絕顯示別名,能顯示數字的全部轉化為數字

-l:僅顯示出有在listen 狀態下的服務狀態

-t:顯示出TCP相關選項

-u:顯示出UDP相關選項

 

 

 

相關文章