簡單的網路程式設計———TCP/UDP
阿新 • • 發佈:2019-01-12
定義
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;
}
實驗現象
虛擬機器上
開發板上