unix C语言关于socket的recv和send的问题,代码中也有问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unix C语言关于socket的recv和send的问题,代码中也有问题相关的知识,希望对你有一定的参考价值。

---------------server.c----------------
int main(int argc, char **argv)

int server_fd;
struct sockaddr_in server_addr;
char buff[4096];
char welcome_msg[] = "hello,welcome to my world!\n";

memset(&server_addr, 0x00, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
server_addr.sin_port = htons(PORT);

server_fd = socket(AF_INET ,SOCK_STREAM, 0);
if(server_fd <0)

printf("socket fail: %s\n", strerror(errno));
return -1;

if(bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)))

printf("bind fail: %s \n",strerror(errno)) ;
return -1;

if(listen(server_fd, MAX_LINK) <0)

printf("listen faile: %s \n", strerror(errno));
return -1;

while(1)

struct sockaddr_in link_addr;
int link_fd;
socklen_t link_addr_len;

link_addr_len = sizeof(link_addr);
memset(&link_addr, 0x00, sizeof(link_addr));
link_fd = accept(server_fd, (struct sockaddr*)&link_addr, &link_addr_len);
send(link_fd, welcome_msg, sizeof(welcome_msg), 0);
memset(buff, 0x00, sizeof(buff));
recv(link_fd, buff, MAX_LEN, 0);
printf("%s",buff);

return 0;

---------------client.c----------------
int main(int argc, char **argv)

int link_fd;
struct sockaddr_in link_addr;
struct sockaddr_in server_addr;
char *ipaddr = argv[1];
int port = atoi(argv[2]);
char buff[MAX_BUF];

memset(&link_addr, 0x00, sizeof(link_addr));
memset(&server_addr, 0x00,sizeof(server_addr));

link_addr.sin_family = AF_INET;
link_addr.sin_addr.s_addr = htons(INADDR_ANY);
link_addr.sin_port = htons(0);

server_addr.sin_family = AF_INET;
/* server_addr.sin_addr.s_addr = htons(ipaddr);*/
这里为何要用下面的?
if (inet_aton(ipaddr,&server_addr.sin_addr) <0)

printf("Server IP Address Error!\n");
return -1;

server_addr.sin_port = htons(port);

link_fd = socket(AF_INET, SOCK_STREAM, 0);
if( link_fd <0 )

printf("socket fail: %s\n",strerror(errno));
return -1;

if( bind(link_fd, (struct sockaddr*)&link_addr, sizeof(link_addr)))

printf("bind faile: %s",strerror(errno));
return -1;

if ( connect(link_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) <0 )

printf("connect to server fail: %s \n", strerror(errno));
return -1;

sprintf(buff,"hello, i come from client");
send(link_fd, buff, strlen(buff)+1, 0);
memset(buff, 0x00, sizeof(buff));
recv(link_fd, buff, MAX_BUF, 0);
printf("recv from server :%s", buff);
sleep(10);
close(link_fd);
return 0;


-------------------问题---------------------
为何这个服务端和客户端通信的时候只有client能收到服务器发来的消息,但是服务端却收不到消息?
htons和inet_aton有什么区别?
这个是代码中提问的
---------------------------------
我要的就是要解决我的代码问题,另外贴的都不要,能正确解答的附赠分数

你的代码其实没有任何问题,之所以 server 没有打印,是由于server最后打印时的代码是
printf("%s",buff);

把它改成
printf("%s\n",buff);
即可。 标准输出是行缓冲的,所以如果打印的内容没有 \n 了话,内容不会真正打印出来,而是留在缓冲中。

至于你client打印时
printf("recv from server :%s", buff);
虽然没有在后面加 \n, 但是你从server发到client的消息里已经带有 \n 了,所以这里没出问题。

关于标准输入输出缓冲相关的更多细节,自己搜一下吧。

htons和inet_aton有什么区别?

htons 是把 主机使用的字节序转成网络字节序 (即入参是整数,返回值也是整数)

而 inet_aton 是吧 ascii 字符串形式的IP地址 转换成 网络字节序的整数。

自己去搜一下网络字节序相关信息。
参考技术A 服务器要想和客户端通信 首先,客户端肯定要是双线程...一个来读 一个来写.. 也就是 一个接受,一个发送...
服务器要多线程 ,每连接一个客户,就多分一个线程,给他用与通信

上面的你可能还没有写,
但你服务器等待到一个客户端的时候是先发送再等待接受,
而客户端也是先发送再等待接受,连上的同时 两边都会 一起发送,这样可能会有数据丢失...
应该是一方发送 另一方再等待接受, 这样才可以通信, 你把客户端或者服务器 send(link_fd, buff, strlen(buff)+1, 0);
和recv(link_fd, buff, MAX_BUF, 0);函数调过来试试追问

这个我也想到过,结果是缓过来依然有问题

追答

留下你的Q 我加你,,, 实在不行分步调试,判断每个函数的返回值,逐行加printf 看都执行到那步

追问

1181291424我也试过分步调试,想输出send和recv后的返回值,结果这个返回值根本无法打印
说明这个函数没有调用过一样,非常奇怪

追答

把客户端的
send(link_fd, buff, strlen(buff)+1, 0);
把strlen换成sizeof试试..

给你发点代码吧...现在班上编译不了所以无法具体改你的代码,你自己对照吧
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 6688
#define SERVER_IP "192.168.7.191"
int main(int argc, char **argv)

int csfd;
int ret;
char msg[100] = "hello!";
struct sockaddr_in server_info;
server_info.sin_family = AF_INET;
server_info.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET,SERVER_IP,&server_info.sin_addr.s_addr);
csfd = socket(AF_INET,SOCK_STREAM,0);
if (csfd < 0)
printf("socket error!\n");
return 1;

ret = connect(csfd,(struct sockaddr*)&server_info,sizeof(struct sockaddr));
if (ret < 0)
printf("connect server error!\n");
return 2;

while(1)
gets(msg);
ret = write(csfd,msg,strlen(msg));
if (ret <= 0)continue;
bzero(msg,sizeof(msg));
ret = read(csfd,msg,sizeof(msg)-1);
if (ret <= 0)break;
printf("from server :%s\n",msg);

close(csfd);
return 0;


上面的是客户端,服务器的发不上去了...Q加你了,如果需要服务器端的再次追问的时候给你发

追问

这个我要的是要找出我代码的问题,不是另外的代码,我这的书上也有能实现的代码,而且我自己重写也能实现,只是这份代码不能实现,我要找出原因

追答

...额,我班上无法调试,没有linux... 能帮你的估计不多了,代码可能就是一点细小的问题,如果自己会了是在没有必要专牛角尖,非要弄明白...重写一份就好,写对了以后用的时候都复制即可,编程不可能所以的代码总是自己重复写..重要的编程思想,明白了也就可以了 ...

以上全是废话,发代码也是因为我是在无能为力了...我在没有编译环境光看代码下能做的真的不多,每次用我也都是复制...或者用别人写好的... 加你Q了,如果想深学网络编程这地方,我记得网络编程是挺厚的一本书那...有的学了

c语言中关于socket函数的例子

求一个c语言中关于socket函数的例子 最好有注释 谢谢!

函数说明:socket()用来建立一个新的socket, 也就是向系统注册, 通知系统建立一通信端口. 参数domain 指定使用何种的地址类型, 完整的定义在/usr/include/bits/socket.h 内, 底下是常见的协议:
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL UNIX 进程通信协议
PF_INET?AF_INET Ipv4 网络协议
PF_INET6/AF_INET6 Ipv6 网络协议
PF_IPX/AF_IPX IPX-Novell 协议
PF_NETLINK/AF_NETLINK 核心用户接口装置
PF_X25/AF_X25 ITU-T X. 25/ISO-8208 协议
PF_AX25/AF_AX25 业余无线AX. 25 协议
PF_ATMPVC/AF_ATMPVC 存取原始 ATM PVCs
PF_APPLETALK/AF_APPLETALK appletalk (DDP)协议
PF_PACKET/AF_PACKET 初级封包接口

参数 type 有下列几种数值:
1、SOCK_STREAM 提供双向连续且可信赖的数据流, 即TCP. 支持 OOB 机制, 在所有数据传送前必须使用connect()来建立连线状态.
2、SOCK_DGRAM 使用不连续不可信赖的数据包连接
3、SOCK_SEQPACKET 提供连续可信赖的数据包连接
4、SOCK_RAW 提供原始网络协议存取
5、SOCK_RDM 提供可信赖的数据包连接
6、SOCK_PACKET 提供和网络驱动程序直接通信. protocol 用来指定socket 所使用的传输协议编号, 通常此参考不用管它, 设为0 即可.

返回值:成功则返回socket 处理代码, 失败返回-1.

错误代码:
1、EPROTONOSUPPORT 参数domain 指定的类型不支持参数type 或protocol 指定的协议
2、ENFILE 核心内存不足, 无法建立新的socket 结构
3、EMFILE 进程文件表溢出, 无法再建立新的socket
4、EACCESS 权限不足, 无法建立type 或protocol 指定的协议
5、ENOBUFS/ENOMEM 内存不足
6、EINVAL 参数domain/type/protocol 不合法
参考技术A 以下是简单socket通信的例子

客户端代码:

// client.c : 定义控制台应用程序的入口点。
//

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

int main()

WSADATA wsadata;
WORD socketversion = MAKEWORD(2,2);
if(::WSAStartup(socketversion,&wsadata) != 0)

printf("启动windows socket失败!\n");


SOCKET clientsocket;
if((clientsocket = ::socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)

printf("创建套接字失败!\n");
::closesocket(clientsocket);
exit(0);


sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(5051);
client.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if(::bind(clientsocket,(sockaddr *)&client,sizeof(client)) == SOCKET_ERROR)

printf("绑定地址失败\n");
::closesocket(clientsocket);
exit(0);


sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(5050);
server.sin_addr.S_un.S_addr = inet_addr("172.19.36.8");
if(::connect(clientsocket,(sockaddr *)&server,sizeof(server)) == SOCKET_ERROR)

printf("服务器连接失败\n");
::closesocket(clientsocket);
exit(0);

printf("服务器连接成功");
while(1)

char buf[1024];
::memset(buf,0,sizeof(buf));
gets(buf);
char *p_c;
int count;
int numchr;
p_c = buf;
//p_c = (LPSTR)(LPCTSTR)m_sendstr;
count = sizeof(buf);
numchr=0;
do

numchr = send(clientsocket,p_c,count,0);
if(numchr == SOCKET_ERROR)

printf("发送错误");

else

p_c+=numchr;
count-=numchr;

while(count>0);

getch();
return 0;

以上是关于unix C语言关于socket的recv和send的问题,代码中也有问题的主要内容,如果未能解决你的问题,请参考以下文章

c语言中关于socket函数的例子

Linux C语言 C/S程序,客户端发送的数据和服务器端接收到的数据不一样,求解

socket 的recv函数返回0应该怎样处理

linux C语言 socket如何判断socket_fd对应的socket是否断开?(是否连通是否正常连接)recv()tcp_info TCP_ESTABLISHEDkeepalive

Socket 编程——recv() 无法获取所有数据

recv原理高阶版黏包解决方案基于UDP的socket通信