linux網絡編程之用socket實現簡單客戶端和服務端的通信(基於UDP)


1、sendto和recvfrom函數介紹


sendto(經socket傳送數據)

相關函數 send , sendmsg,recv , recvfrom , socket
表頭文件 #include < sys/types.h >
#include < sys/socket.h >
定義函數 int sendto ( int s , const void * msg, int len, unsigned int flags, const
struct sockaddr * to , int tolen ) ;
函數說明 sendto() 用來將數據由指定的socket傳給對方主機。參數s為已建好連線的socket,如果利用UDP協議則不需經過連線操作。參數msg指向欲連線的數據內容,參數flags 一般設0,詳細描述請參考send()。參數to用來指定欲傳送的網絡地址,結構sockaddr請參考bind()。參數tolen為sockaddr的結果長度。
返回值 成功則返回實際傳送出去的字符數,失敗返回-1,錯誤原因存於errno 中。
錯誤代碼 EBADF 參數s非法的socket處理代碼。
EFAULT 參數中有一指針指向無法存取的內存空間。
WNOTSOCK canshu s為一文件描述詞,非socket。
EINTR 被信號所中斷。
EAGAIN 此動作會令進程阻斷,但參數s的soket為補課阻斷的。
ENOBUFS 系統的緩沖內存不足。
EINVAL 傳給系統調用的參數不正確。

 

 

recvfrom(經socket接收數據)

 

相關函數 recv,recvmsg,send,sendto,socket
表頭文件 #include<sys/types.h>
#include<sys/socket.h>
定義函數 int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
函數說明 recv()用來接收遠程主機經指定的socket 傳來的數據,並把數據存到由參數buf 指向的內存空間,參數len 為可接收數據的最大長度。參數flags 一般設0,其他數值定義請參考recv()。參數from用來指定欲傳送的網絡地址,結構sockaddr 請參考bind()。參數fromlen為sockaddr的結構長度。
返回值 成功則返回接收到的字符數,失敗則返回-1,錯誤原因存於errno中。
錯誤代碼 EBADF 參數s非合法的socket處理代碼
EFAULT 參數中有一指針指向無法存取的內存空間。
ENOTSOCK 參數s為一文件描述詞,非socket。
EINTR 被信號所中斷。
EAGAIN 此動作會令進程阻斷,但參數s的socket為不可阻斷。
ENOBUFS 系統的緩沖內存不足
ENOMEM 核心內存不足
EINVAL 傳給系統調用的參數不正確。



2、單客戶端和服務端的通信(基於UDP)   圖解



3、單客戶端和服務端的通信(基於UDP)   代碼


1、服務端代碼socket3.c

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

#define PORT 8888
#define MAX_MSG_SIZE 1024

int main(void)
{
int sockfd, addrlen, n;
struct sockaddr_in addr;
char msg[MAX_MSG_SIZE];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
fprintf(stderr, "socket failed\n");
exit(EXIT_FAILURE);
}
addrlen = sizeof(struct sockaddr_in);
bzero(&addr, addrlen);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr*)(&addr), addrlen) < 0)
{
fprintf(stderr, "bind fail\n");
exit(EXIT_FAILURE);
}
puts("bind success");
while (1)
{
bzero(msg, MAX_MSG_SIZE);
n = recvfrom(sockfd, msg, sizeof(msg), 0, (struct sockaddr *)(&addr), &addrlen);
fprintf(stdout, "Recevie message from client is %s\n", msg);
fgets(msg, MAX_MSG_SIZE,stdin);
printf("Server endpoint input message %s\n", msg);
sendto(sockfd, msg, n, 0,(struct sockaddr *)(&addr), addrlen);
}
close(sockfd);
exit(EXIT_SUCCESS);
}


2、客戶端代碼socket4.c


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

#define MAX_BUF_SIZE 1024
#define PORT 8888

int main()
{
int sockfd, addrlen, n;
char buffer[MAX_BUF_SIZE];
struct sockaddr_in addr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
fprintf(stderr, "socket falied\n");
exit(EXIT_FAILURE);
}
addrlen = sizeof(struct sockaddr_in);
bzero(&addr, addrlen);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

puts("socket success");
while(1)
{
bzero(buffer, MAX_BUF_SIZE);
fgets(buffer, MAX_BUF_SIZE, stdin);
sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)(&addr), addrlen);
printf("client send msg is %s\n", buffer);
n = recvfrom(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)(&addr), &addrlen);
fprintf(stdout, "clinet Receive message from server is %s\n", buffer);
}
close(sockfd);
exit(0);
return 0;
}



4、運行結果



5、總結

服務端:socket->bind->(sendto 、revcfrom)

客戶端:socket->(sendto 、revcfrom)

upd不是面相連接的,這個是和tcp本質區別,數據可能會亂序,重復。




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com