发送端
#include "head.h"
int sockfd = 0;
pthread_t tid_send;
pthread_t tid_recv;
struct sockaddr_in recvaddr ;
char name[32];
void *sendfun(void *arg)
{
struct msgbuf sendmsg;
ssize_t nsize = 0;
while(1)
{
memset(&sendmsg,0,sizeof(sendmsg));
sendmsg.type = MSG_TYPE_CHAT;
sprintf(sendmsg.name,"%s",name);
gets(sendmsg.text);
if (strcmp(sendmsg.text,".quit")==0)
{
sendmsg.type = MSG_TYPE_END;
}
nsize =sendto(sockfd,&sendmsg,sizeof(sendmsg),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
if(sendmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_recv);
return NULL;
}
void *recvfun(void *arg)
{
struct msgbuf recvmsg;
ssize_t nsize = 0;
while (1)
{
memset(&recvmsg, 0, sizeof(recvmsg));
nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);
if (-1 == nsize)
{
perror("fail to recvfrom");
return NULL;
}
if (recvmsg.type == MSG_TYPE_CHAT)
{
printf("%s(%s:%d)>%s\n", recvmsg.name, RECV_ADDR, RECV_PORT, recvmsg.text);
}
else if (recvmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_send);
return NULL;
}
int main(void)
{
struct msgbuf sendmsg;
ssize_t nsize = 0;
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);
printf("输入你的名字:");gets(name);
sockfd = socket(AF_INET,SOCK_DGRAM,0);
memset(&sendmsg,0,sizeof(sendmsg));
sendmsg.type = MSG_TYPE_START;
sprintf(sendmsg.name,"%s",name);
nsize = sendto(sockfd,&sendmsg,sizeof(sendmsg),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
pthread_create(&tid_send,NULL,sendfun,NULL);
pthread_create(&tid_recv,NULL,recvfun,NULL);
pthread_join(tid_send,NULL);
pthread_join(tid_recv,NULL);
close(sockfd);
return 0;
}
接收端
#include "head.h"
char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;
pthread_t tid_send;
pthread_t tid_recv;
void *sendfun(void *arg)
{
struct msgbuf sendmsg;
ssize_t nsize = 0;
while (1)
{
memset(&sendmsg, 0, sizeof(sendmsg));
sendmsg.type = MSG_TYPE_CHAT;
sprintf(sendmsg.name, "%s", name);
gets(sendmsg.text);
if (!strcmp(sendmsg.text, ".quit"))
{
sendmsg.type = MSG_TYPE_END;
}
nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
if (-1 == nsize)
{
perror("fail to sendto");
return NULL;
}
if (sendmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_recv);
return NULL;
}
void *recvfun(void *arg)
{
struct msgbuf recvmsg;
ssize_t nsize = 0;
while (1)
{
memset(&recvmsg, 0, sizeof(recvmsg));
nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);
if (-1 == nsize)
{
perror("fail to recvfrom");
return NULL;
}
if (recvmsg.type == MSG_TYPE_CHAT)
{
printf("%s(%s:%d)>%s\n", recvmsg.name, inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), recvmsg.text);
}
else if (recvmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_send);
return NULL;
}
int main(void)
{
struct msgbuf recvmsg;
ssize_t nsize = 0;
int ret = 0;
socklen_t addrlen = sizeof(sendaddr);
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);
printf("请输入您的昵称:\n");
gets(name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("fail to socket");
return -1;
}
ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
memset(&recvmsg, 0, sizeof(recvmsg));
nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, (struct sockaddr *)&sendaddr, &addrlen);
if (-1 == nsize)
{
perror("fail to recvfrom");
return -1;
}
pthread_create(&tid_send, NULL, sendfun, NULL);
pthread_create(&tid_recv, NULL, recvfun, NULL);
pthread_join(tid_send, NULL);
pthread_join(tid_recv, NULL);
close(sockfd);
return 0;
}
.UDP编程
1.发端:
socket套接字 编程:
socket
int socket(int domain, int type, int protocol);
功能:
创建一个用来通信的文件描述符
参数:
domain:使用的协议族 AF_INET (IPv4协议族)
type:套接字类型
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
SOCK_RAW:原始套接字
protocol:协议
默认为0
返回值:
成功返回文件描述符
失败返回-1
sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
利用套接字向指定地址发送数据信息
参数:
sockfd:套接字文件描述符
buf:发送数据空0间首地址
len:发送数据的长度
flags:属性默认为0
dest_addr:目的地址信息存放的空间首地址
addrlen:目的地址的长度
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
返回值:
成功返回实际发送字节数
失败返回-1
inet_addr:
in_addr_t inet_addr(const char *cp);
功能:
将字符串IP地址转换为内存中的IP地址
htons
uint16_t htons(uint16_t hostshort);
功能:
将本地字节序转换为网络的大端字节序
close
收端
1.recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:
从套接字中接收数据
参数:
sockfd:套接字文件描述符
buf:存放数据空间首地址
flags:属性 默认为0
src_addr:存放IP地址信息的空间首地址
addrlen:存放接收到IP地址大小空间的首地址
返回值:
成功返回实际接收字节数
失败返回-1
2.bind
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:
在套接字上绑定一个IP地址和端口号
参数:
sockfd:套接字文件描述符
addr:绑定IP地址空间首地址
addrlen:绑定IP地址的长度
返回值:
成功返回0
失败返回-1