1. 程式人生 > >簡單的網路程式設計———TCP/UDP

簡單的網路程式設計———TCP/UDP

定義
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)協議屬於傳輸層協議。其中TCP提供IP環境下的資料可靠傳輸,它提供的服務包括資料流傳送、可靠性、有效流控、全雙工操作和多路複用。通過面向連線、端到端和可靠的資料包傳送。通俗說,它是事先為所傳送的資料開闢出連線好的通道,然後再進行資料傳送;

UDP則不為IP提供可靠性、流控或差錯恢復功能。
一般來說,TCP對應的是可靠性要求高的應用,而UDP對應的則是可靠性要求低、傳輸經濟的應用。TCP支援的應用協議主要有:Telnet、FTP、SMTP等;UDP支援的應用層協議主要有:NFS(網路檔案系統)、SNMP(簡單網路管理協議)、DNS(主域名稱系統)、TFTP(通用檔案傳輸協議)等。

TCP:“面向連線”就是在正式通訊前必須要與對方建立起連線。
UDP(User Data Protocol,使用者資料報協議)是與TCP相對應的協議。它是面向非連線的協議,它不與對方建立連線,而是直接就把資料包傳送過去!“面向非連線”就是在正式通訊前不必與對方先建立連線,不管對方狀態就直接傳送。

TCP服務端程式

#include <sys/types.h>        
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <signal.h> /* socket 建立 * bind 繫結ip、埠 * listen 監聽 * accept 接收客戶端連線 * send/recv 傳送接收 */ #define SERVER_PORT 8888 #define BACKLOG 10 //監聽路數 int main(int argc, char **argv) { int iSocketServer; int
iSocketClient; struct sockaddr_in tSocketServerAddr; struct sockaddr_in tSocketClientAddr; int iRet; int iAddrLen; int iRecvLen; unsigned char ucRecvBuf[1000]; int iClientNum = -1; signal(SIGCHLD,SIG_IGN);//清理子程序(殭屍程序) /*IPV4,TCP*/ iSocketServer = socket(AF_INET, SOCK_STREAM, 0); if (-1 == iSocketServer) { printf("socket error!\n"); return -1; } tSocketServerAddr.sin_family = AF_INET; tSocketServerAddr.sin_port = htons(SERVER_PORT); /* 監測埠 */ tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;/*本機所有ip*/ memset(tSocketServerAddr.sin_zero, 0, 8); /*繫結IP地址、埠等資訊到socket上*/ iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr)); if (-1 == iRet) { printf("bind error!\n"); return -1; } iRet = listen(iSocketServer, BACKLOG);//可監聽10個客戶端 if (-1 == iRet) { printf("listen error!\n"); return -1; } while (1) { iAddrLen = sizeof(struct sockaddr); /* 等待客戶端連線 儲存客戶端地址 地址長度*/ iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen); if (-1 != iSocketClient)//有客戶端連線 { iClientNum++; /* 得到ip*/ printf("Get connect from client %d : %s\n", iClientNum, inet_ntoa(tSocketClientAddr.sin_addr)); /*對每一個客戶端連線建立子程序*/ if (!fork()) { /* 子程序的原始碼 */ while (1) { /* 接收客戶端發來的資料並打印出來 */ iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0); if (iRecvLen <= 0) { close(iSocketClient); return -1; } else { ucRecvBuf[iRecvLen] = '\0'; printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf); } } } } } close(iSocketServer); return 0; }

TCP客戶端程式

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket
 * connect
 * send/recv
 */

#define SERVER_PORT 8888

/*輸入伺服器ip:192.168.1.11*/
int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;

	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]);
		return -1;
	}

	iSocketClient = socket(AF_INET, SOCK_STREAM, 0);

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))//傳入伺服器ip
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

		/*連線到伺服器*/
	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}

	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))//從標準輸入獲得資料,以回車結束
		{
			iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
			if (iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	
	return 0;
}


SOCK_STREAM這種的特點是面向連線的,即每次收發資料之前必須通過connect建立連線;
SOCK_DGRAM這種是User Datagram Protocol協議的網路通訊,它是無連線的,不可靠的。

UDP服務端程式

#include <sys/types.h>       
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>


/* socket
 * bind
 * sendto/recvfrom
 */
#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketServer;
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet;
	int iAddrLen;
	int iRecvLen;
	unsigned char ucRecvBuf[1000];
	int iClientNum = -1;
															/*UDP連線*/
	iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);
	
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if (iRecvLen > 0)
		{
			ucRecvBuf[iRecvLen] = '\0';
			printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
		}
	}
	close(iSocketServer);
	return 0;
}

UDP客戶端程式

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket
 * sendto/recvfrom
 * 
 *	使用connect,使用send/recv進行收發
 *不是使用connect,使用sendto/recvfrom進行收發
 */


#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;

	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]);
		return -1;
	}

	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

/*
	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}
*/
	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))
		{
			//iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
			iSendLen = sendto(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0, (const struct sockaddr *)&tSocketServerAddr, iAddrLen);
			if (iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	return 0;
}

實驗現象
虛擬機器上
在這裡插入圖片描述
開發板上
在這裡插入圖片描述