實現簡單UDP伺服器客戶端模型
阿新 • • 發佈:2019-02-01
UDP是無連線的,在資料的傳送之前不需要連線,只需要知道要發資料給誰,然後將資料發出即可,可以直接接收到其他人發來的資料,不必呼叫listen()和accept()函式。所以UDP中建立好套接字後,就可以直接進行資料的傳輸。
基於UDP的接收和傳送函式:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
函式說明:
sendto() 用來將資料由指定的socket 傳給對方主機.
引數描述:
sockfd: 為已建好連線的socket, 如果利用UDP協議則不需經過連線操作
buf: 緩衝區
len:buf的大小
flags: 一般設0
dest_addr: 用來指定欲傳送的網路地址, 結構sockaddr 請參考bind()
addrlen: 為sockaddr 的結構長度.
返回值:
成功則返回實際傳送出去的字元數, 失敗返回-1, 錯誤原因存於errno 中.
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
函式說明:
用來接收遠端主機經指定的socket 傳來的資料, 並把資料存到由引數buf 指向的記憶體空間
引數描述:
sockfd:為已建好連線的socket
buf:緩衝區
len:buf大小
flags:收取收取資料的方式
src_addr: 用來指定欲傳送的網路地址, 結構sockaddr 請參考bind()
addrlen:為sockaddr 的結構長度
返回值:
成功則返回接收到的字元數,失敗返回-1,錯誤原因存於errno 中.
server: #include<stdio.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> #include<stdlib.h> static void usage(char* proc) { printf("Usage: %s [local_ip] [local_port]", proc); } int main(int argc, char* argv[]) { if(argc != 3) { usage(argv[0]); } //建立套接字 int sock = socket(AF_INET, SOCK_DGRAM,0); if(sock < 0) { perror("sock"); return 1; } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(atoi(argv[2])); local.sin_addr.s_addr = inet_addr(argv[1]); //將套接字描述符與IP和埠號進行繫結 if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0 ) { perror("bind"); return 2; } struct sockaddr_in client; char buf[1024]; while(1) { socklen_t len = sizeof(client); //接受客戶端發來的資訊,將客戶端的套接字資訊儲存於client裡 ssize_t s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&client, &len); if(s > 0) { buf[s] = 0; printf("client [%s] [%d]: %s", inet_ntoa(client.sin_addr), ntohs(client.sin_port),buf); printf("Server : "); fflush(stdout); //從鍵盤讀入資訊 int _s = read(0, buf, sizeof(buf)-1); buf[_s-1] = 0; //傳送資訊到客戶端 sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&client, sizeof(client)); } else { perror("recvfrom"); return 3; } } return 0; }
client:
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<sys/types.h>
static void Usage(char *proc)
{
printf("Usage %s [server_ip] [server_port]\n", proc);
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
Usage(argv[0]);
return 1;
}
//建立套接字, 注意使用udp套接字程式設計時應注意模式為SOCK_DGRAM
int sock = socket(AF_INET, SOCK_DGRAM,0);
if(sock < 0)
{
perror("socket");
return 2;
}
//獲取伺服器套接字資訊
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
char buf[1024];
int len = sizeof(server);
//用peer接收發送給客戶端的遠端主機socket資訊
struct sockaddr_in peer;
while(1)
{
printf("Please Enter# ");
fflush(stdout);
//從鍵盤寫入內容到緩衝區
ssize_t s = read(0, buf, sizeof(buf)-1);
buf[s] = 0;
socklen_t len1 = sizeof(peer);
if(s >0)
{
printf("server# ");
//將緩衝區內容通過套接字傳送到伺服器
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&server, sizeof(server));
//在從套接字中讀取伺服器的迴應資訊
ssize_t _s = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&peer, &len1);
if(_s > 0)
{
buf[_s] = 0;
printf("%s\n", buf);
}
}
}
return 0;
}