server端:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#define PORT 7089
#define BUFFER_SIZE 1024
#define MAX_QUE_CONN_NM 5
struct sockaddr_in server_sockaddr;
int sin_size,recvbytes,sendbytes;
int sockfd, client_fd;
char buf[BUFFER_SIZE];
char message[72];
void *thrd_send()
{
while(1){
memset(buf, 0, sizeof(buf));
printf("请输入 message:\n");
scanf("%s",&message);
sprintf(buf, "%s", message);
/*发送消息给服务器端*/
if ((sendbytes = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr))) == -1)
{
perror("send");
exit(1);
}
}
}
int main()
{
pthread_t thread[1];
/*建立 socket 连接*/
if ((sockfd = socket(AF_INET,SOCK_DGRAM,0))== -1)
{
perror("socket");
exit(1);
}
printf("Socket id = %d\n",sockfd);
/*设置 sockaddr_in 结构体中相关参数*/
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(PORT);
server_sockaddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_sockaddr.sin_zero), 8);
int i = 1;/* 允许重复使用本地地址与套接字进行绑定 */
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
/*绑定函数 bind()*/
if (bind(sockfd, (struct sockaddr *)&server_sockaddr,sizeof(struct
sockaddr)) == -1)
{
perror("bind");
exit(1);
}
printf("Bind success!\n");
int getlen = sizeof(server_sockaddr);
while(1){
memset(buf , 0, sizeof(buf));
/*调用 recv()函数接收客户端的请求*/
if ((recvbytes = recvfrom(sockfd, buf, BUFFER_SIZE, 0, (struct sockaddr *)&server_sockaddr, (socklen_t*)&getlen)) == -1)
{
perror("recv");
exit(1);
}
else if(recvbytes==0)
{
printf("失败\n");
exit(1);
}
printf("Received a message: %s\n", buf);
pthread_create(&thread[0],NULL,thrd_send,(void*)0);
}
close(sockfd);
exit(0);
}
client端:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#define PORT 7089
#define BUFFER_SIZE 1024
int sockfd,sendbytes,recvbytes;
char buf[BUFFER_SIZE];
char ip[36];
char message[72];
struct hostent *host;
struct sockaddr_in serv_addr;
void *thrd_recv()
{
int addr_len=sizeof(serv_addr);
while(1){
memset(buf , 0, sizeof(buf));
if ((recvbytes = recvfrom(sockfd, buf, BUFFER_SIZE, 0, (struct sockaddr *)&serv_addr, (socklen_t*)&addr_len)) == -1)
{
perror("recv");
exit(1);
}
printf("Received a message: %s\n", buf);
}
}
int main()
{
pthread_t thread[1];
printf("请输入对方 IP 或者主机名\n");
scanf("%s",&ip);
printf("对方 IP 或者主机名是:%s\n",ip);
if ((host = gethostbyname(ip) )== NULL)
{
perror("gethostbyname");
exit(1);
}
/*创建 socket*/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}
/*设置 sockaddr_in 结构体中相关参数*/
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero), 8);
/*调用 connect 函数主动发起对服务器端的连接*/
while(1){
pthread_create(&thread[0],NULL,thrd_recv,(void*)0);
memset(buf, 0, sizeof(buf));
printf("请输入 message:\n");
scanf("%s",&message);
sprintf(buf, "%s", message);
/*发送消息给服务器端*/
if ((sendbytes = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) == -1)
{
perror("sendto");
exit(1);
}
}
close(sockfd);
exit(0);
}
要注意的是:udp客户端连接服务端时,服务端并不知道客户端的端口号,因为客户端的udp端口号是系统自动分配的,所以服务端不能先发送数据给客户端。因此只有当客户端先发送数据给服务端,服务端才能知道客户端的udp端口号。
为了解决此问题,客户端可自己设定udp端口号,也就是监听端口。添加bind函数即可:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#define PORT 7089
#define BUFFER_SIZE 1024
int sockfd,sendbytes,recvbytes;
char buf[BUFFER_SIZE];
char ip[36];
char message[72];
struct hostent *host;
struct sockaddr_in serv_addr;
struct sockaddr_in serverGet;
void *thrd_recv()
{
int addr_len=sizeof(serv_addr);
int getlen=sizeof(serverGet);
while(1){
memset(buf , 0, sizeof(buf));
if ((recvbytes = recvfrom(sockfd, buf, BUFFER_SIZE, 0, (struct sockaddr *)&serverGet, (socklen_t*)&getlen)) == -1)
{
perror("recv");
exit(1);
}
printf("Received a message: %s\n", buf);
}
}
int main()
{
pthread_t thread[1];
printf("请输入对方 IP 或者主机名\n");
scanf("%s",&ip);
printf("对方 IP 或者主机名是:%s\n",ip);
if ((host = gethostbyname(ip) )== NULL)
{
perror("gethostbyname");
exit(1);
}
/*创建 socket*/
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket");
exit(1);
}
/*设置 sockaddr_in 结构体中相关参数*/
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero), 8);
/*调用 bind 函数绑定本地监听端口,这里是7089*/
int getlen=sizeof(serverGet);
serverGet.sin_family=AF_INET;
serverGet.sin_port=htons(7089);
serverGet.sin_addr.s_addr=INADDR_ANY;
bind(sockfd,(struct sockaddr*)&serverGet,getlen);
while(1){
pthread_create(&thread[0],NULL,thrd_recv,(void*)0);
memset(buf, 0, sizeof(buf));
printf("请输入 message:\n");
scanf("%s",&message);
sprintf(buf, "%s", message);
/*发送消息给服务器端*/
if ((sendbytes = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) == -1)
{
perror("sendto");
exit(1);
}
}
close(sockfd);
exit(0);
}