关于套接字的send/recv的初级问题 很初级 初学者困惑
#include
#include
#include
#include
#include
#include
#include
#define LINE 2048
pthread_mutex_t work = PTHREAD_MUTEX_INITIALIZER;
struct sockaddr_in tcpsock, udpsock;
void *handle_tcp(void *arg)
{
int tcpfd = *((int *)arg);
int tcpcon;
int n;
char *suc = "success";
socklen_t len = 0;
struct sockaddr_in tcpcli;
listen(tcpfd, 20);
char str[INET_ADDRSTRLEN];
char buf[LINE];
while(1)
{
len = sizeof(tcpcli);
tcpcon = accept(tcpfd, (struct sockaddr*)&tcpcli, &len);
pthread_mutex_lock(&work);
printf("receive from %s at port %d\n",
inet_ntop(PF_INET, &tcpcli.sin_addr, str, sizeof(str)),
ntohs(tcpcli.sin_port));
pthread_mutex_unlock(&work);
while(1)
{
if((n = read(tcpcon, buf, LINE)) == 0)
{
close(tcpcon);
break;
}
else
{
pthread_mutex_lock(&work);
printf("[message=%s]\n", buf);
pthread_mutex_unlock(&work);
write(tcpcon, suc, 8);
}
}
}
}
void *handle_udp(void *arg)
{
int udpfd = *((int *)arg);
socklen_t len;
struct sockaddr_in udpcli;
int n;
char buf[LINE];
char *suc = "success";
while(1)
{
len = sizeof(udpcli);
if((n = recvfrom(udpfd, buf, LINE, 0, (struct sockaddr*)&udpcli, &len)) == -1)
{
pthread_mutex_lock(&work);
fprintf(stderr, "recvfrom error\n");
pthread_mutex_unlock(&work);
}
else
{
printf("[len=%d]\n", atoi(buf));
}
if((n = sendto(udpfd, suc, 8, 0, (struct sockaddr*)&udpcli, sizeof(udpcli))) == -1)
{
pthread_mutex_lock(&work);
fprintf(stderr, "sendto error\n");
pthread_mutex_unlock(&work);
}
}
}
int main(void)
{
int udpfd, tcpfd;
tcpfd = socket(PF_INET, SOCK_STREAM, 0);
udpfd = socket(PF_INET, SOCK_DGRAM, 0);
pthread_t tcP, udP;
int ret;
bzero(&tcpsock, sizeof(tcpsock));
bzero(&udpsock, sizeof(udpsock));
tcpsock.sin_port = htons(8000);
tcpsock.sin_family = PF_INET;
tcpsock.sin_addr.s_addr = htonl(INADDR_ANY);
udpsock.sin_family = PF_INET;
udpsock.sin_port = htons(8000);
udpsock.sin_addr.s_addr = htonl(INADDR_ANY);
bind(tcpfd, (struct sockaddr*)&tcpsock, sizeof(tcpsock));
bind(udpfd, (struct sockaddr*)&udpsock, sizeof(udpsock));
printf("waitting message......................\n");
if((ret = pthread_create(&tcP, NULL, handle_tcp, (void*)&tcpfd)) != 0)
{
fprintf(stderr, "can't create tcp thread:%s\n", strerror(ret));
exit(1);
}
if((ret = pthread_create(&udP, NULL, handle_udp, (void*)&udpfd)) != 0)
{
fprintf(stderr, "can't create udp thread:%s\n", strerror(ret));
exit(1);
}
while(1);
return 0;
}
现给你看个我自己写的代码,这个是个服务器,功能是利用tcp协议接受客户端发来的字符串,用UDP接收到客户端发来的字符串长度。
read和write是tcp协议时用的接收和发送函数;
sendto和recvfrom是udp接收和发送的函数;
你可以看到read函数有个int型的返回值,是你实际读到的长度。
同样write也是。但是如果你的缓冲区只有1024字节你往里写大于1024的数据程序就直接蹦了,因为你越界了。
所谓的多次发送,是网卡驱动的一种机制,他分为随到随发,和到满再发,
具体跟驱动实现有关,这个就不用你关心了。
sendto返回的意思跟write一样你实际写多少返回的就是多少。
recvfrom是什么时候返回?
你知道阻塞机制吗。读不到东西的时候他就在哪阻塞上了,并不往下继续进行。
对于两端来说一端发送了,另一端就肯定读到了。
如果你说我分着读阿,我有个文件非常大,需要好多次才能发送完阿,怎么办?
很简单,把文件长度给对方发过去,另一段读到后累计长度看看对不对,不对继续读阿。。。。。。。。也就是所谓的同步机制。
UDP协议是无连接的,他只管发不管对方是否在线,读端也一样只管读,不管谁发的什么时候发的。
我不知道你在哪看到的你给shento安排工作,他不完成就返回了。
shento出错才可能出现你说的那种情况。
也就是返回值是-1。
还有就是shendto返回跟recvfrom返回没关系的。
同样recvfrom返回-1也说是错误了,你就可以关闭程序。
你要是问我什么时候可能返回-1。
情况不多。系统出问题了导致轮转错误。我没研究过。
我qq230635800
以前经常写socket代码
有什么问题 可以问问我哦~!!!
Ssize_t write(int fd,const void *buf,size_t nbytes);
write的返回值大于0,表示写了部分数据或者是全部的数据,这样用一个while循环不断的写入数据,但是循环过程中的buf参数和nbytes参数是我们自己来更新的,返回值小于0,此时出错了,需要根据错误类型进行相应的处理
Ssize_t read(int fd,void *buf,size_t nbyte)
Read函数是负责从fd中读取内容,当读取成功时,read返回实际读取到的字节数,如果返回值是0,表示已经读取到文件的结束了,小于0表示是读取错误。
Recv函数和send函数
Recv函数和read函数提供了read和write函数一样的功能,不同的是他们提供了四个参数。
Int
recv(int fd,void *buf,int len,int flags)
Int
send(int fd,void *buf,int len,int flags)
前面的三个参数和read、write函数是一样的。第四个参数可以是0或者是一下组合:
MSG_DONTROUTE:不查找表
是send函数使用的标志,这个标志告诉IP,目的主机在本地网络上,没有必要查找表,这个标志一般用在网络诊断和路由程序里面。
MSG_OOB:接受或者发生带外数据
表示可以接收和发送带外数据。
MSG_PEEK:查看数据,并不从系统缓冲区移走数据
是recv函数使用的标志,表示只是从系统缓冲区中读取内容,而不清楚系统缓冲区的内容。这样在下次读取的时候,依然是一样的内容,一般在有过个进程读写数据的时候使用这个标志。
MSG_WAITALL:等待所有数据
是recv函数的使用标志,表示等到所有的信息到达时才返回,使用这个标志的时候,recv返回一直阻塞,直到指定的条件满足时,或者是发生了错误。
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!