发布网友 发布时间:2022-04-25 14:46
共3个回答
热心网友 时间:2023-10-09 19:43
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#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代码
有什么问题 可以问问我哦~!!!
热心网友 时间:2023-10-09 19:44
第一个问题发送时。有一个缓冲区。如果一次发不完。它会自己接着发。不用人为的在管 !
这儿你没有理解我说的意思。我的意思是说。缓冲区中间的。比如。你定的缓冲区数据是4mb 你发少过4mb 它也不会一次发完的。在网络上他会分很多个包向外发出去。 他会很多次发。对这儿你不用管它。 你说的是。比如有个10MB的数据。你不可能一下定一个10MB的缓冲区吧。因故。你得把数据分成几次发送。这想这个不用那样难理解吧! 你想发几次都行。但数据不能大过缓冲区。
第二个问韪
表示成功发出去的实际长度
第三个。
Send 当发完返回
recv 当接收完毕或缓冲区懑反回一个消息
热心网友 时间:2023-10-09 19:44
想法太多,send调用了,你的数据要么发送成功,要么发送失败,你刚学,应该是堵塞模式,不需要重新发,异步模式,也不需要你重新发,会将你的buffer拷贝到发送缓冲区,这是有socket维护的,和你没有关系.使用wsasend等异步I_O要得到成功操作消息才能释放自己的BUFFER,因此你不需要担心是否发送完全,要么全发送出去,要么失败一点也没发送,至于recv,如果是tcp的话,会一个send后有多个recv,udp则是一一对应的,不过UDP超过包大小会分包,慢慢来,别急,目前你的buffer不需要你担心会发送一办,但你别申请个10MB的buffer,那样阻塞效率很低的