socket编程中recv与send函数

recv函数会将套接字缓冲区中的内容读出,但不清空,与read函数的区别在此。此函数有一个flag标志位,设为MSG_PEEK。

send函数会将缓冲区中的内容写入到套接字,也不清空,与write函数的区别在此。

用这两个函数可以先接收或发送缓冲区中的内容,然后再用readn(此时缓冲区中的内容依然存在)与write函数去继续判断换行符/n,对缓冲区内容实现换行输出。

echocli.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

ssize_t readn(int fd, void *buf, size_t count)

{

size_t nleft = count;

ssize_t nread;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nread = read(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nread == 0)

return count - nleft;

bufp += nread;

nleft -= nread;

}

return count;

}

ssize_t writen(int fd, const void *buf, size_t count)

{

size_t nleft = count;

ssize_t nwritten;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nwritten = write(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nwritten == 0)

continue;

bufp += nwritten;

nleft -= nwritten;

}

return count;

}

ssize_t recv_peek(int sockfd, void *buf, size_t len)

{

while (1)

{

int ret = recv(sockfd, buf, len, MSG_PEEK);

if (ret == -1 && errno == EINTR)

continue;

return ret;

}

}

ssize_t readline(int sockfd, void *buf, size_t maxline)

{

int ret;

int nread;

char *bufp = buf;

int nleft = maxline;

while (1)

{

ret = recv_peek(sockfd, bufp, nleft);

if (ret < 0)

return ret;

else if (ret == 0)

return ret;

nread = ret;

int i;

for (i=0; i<nread; i++)

{

if (bufp[i] == ‘\n‘)

{

ret = readn(sockfd, bufp, i+1);

if (ret != i+1)

exit(EXIT_FAILURE);

return ret;

}

}

if (nread > nleft)

exit(EXIT_FAILURE);

nleft -= nread;

ret = readn(sockfd, bufp, nread);

if (ret != nread)

exit(EXIT_FAILURE);

bufp += nread;

}

return -1;

}

void echo_cli(int sock)

{

char sendbuf[1024] = {0};

char recvbuf[1024] = {0};

while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)

{

writen(sock, sendbuf, strlen(sendbuf));

int ret = readline(sock, recvbuf, sizeof(recvbuf));

if (ret == -1)

ERR_EXIT("readline");

else if (ret == 0)

{

printf("client close\n");

break;

}

fputs(recvbuf, stdout);

memset(sendbuf, 0, sizeof(sendbuf));

memset(recvbuf, 0, sizeof(recvbuf));

}

close(sock);

}

int main(void)

{

int sock;

if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)

ERR_EXIT("socket");

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("connect");

struct sockaddr_in localaddr;

socklen_t addrlen = sizeof(localaddr);

if (getsockname(sock, (struct sockaddr*)&localaddr, &addrlen) < 0)

ERR_EXIT("getsockname");

printf("ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));

echo_cli(sock);

return 0;

}

echosrv.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#include <sys/wait.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

ssize_t readn(int fd, void *buf, size_t count)

{

size_t nleft = count;

ssize_t nread;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nread = read(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nread == 0)

return count - nleft;

bufp += nread;

nleft -= nread;

}

return count;

}

ssize_t writen(int fd, const void *buf, size_t count)

{

size_t nleft = count;

ssize_t nwritten;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nwritten = write(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nwritten == 0)

continue;

bufp += nwritten;

nleft -= nwritten;

}

return count;

}

ssize_t recv_peek(int sockfd, void *buf, size_t len)

{

while (1)

{

int ret = recv(sockfd, buf, len, MSG_PEEK);

if (ret == -1 && errno == EINTR)

continue;

return ret;

}

}

ssize_t readline(int sockfd, void *buf, size_t maxline)

{

int ret;

int nread;

char *bufp = buf;

int nleft = maxline;

while (1)

{

ret = recv_peek(sockfd, bufp, nleft);

if (ret < 0)

return ret;

else if (ret == 0)

return ret;

nread = ret;

int i;

for (i=0; i<nread; i++)

{

if (bufp[i] == ‘\n‘)

{

ret = readn(sockfd, bufp, i+1);

if (ret != i+1)

exit(EXIT_FAILURE);

return ret;

}

}

if (nread > nleft)

exit(EXIT_FAILURE);

nleft -= nread;

ret = readn(sockfd, bufp, nread);

if (ret != nread)

exit(EXIT_FAILURE);

bufp += nread;

}

return -1;

}

void echo_srv(int conn)

{

char recvbuf[1024];

while (1)

{

memset(recvbuf, 0, sizeof(recvbuf));

int ret = readline(conn, recvbuf, 1024);

if (ret == -1)

ERR_EXIT("readline");

if (ret == 0)

{

printf("client close\n");

break;

}

fputs(recvbuf, stdout);

writen(conn, recvbuf, strlen(recvbuf));

}

}

void handle_sigchld(int sig)

{

/*    wait(NULL);*/

while (waitpid(-1, NULL, WNOHANG) > 0)

;

}

int main(void)

{

/*    signal(SIGCHLD, SIG_IGN);*/

signal(SIGCHLD, handle_sigchld);

int listenfd;

if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)

/*    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)*/

ERR_EXIT("socket");

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

/*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/

/*inet_aton("127.0.0.1", &servaddr.sin_addr);*/

int on = 1;

if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)

ERR_EXIT("setsockopt");

if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("bind");

if (listen(listenfd, SOMAXCONN) < 0)

ERR_EXIT("listen");

struct sockaddr_in peeraddr;

socklen_t peerlen = sizeof(peeraddr);

int conn;

pid_t pid;

while (1)

{

if ((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)

ERR_EXIT("accept");

printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

pid = fork();

if (pid == -1)

ERR_EXIT("fork");

if (pid == 0)

{

close(listenfd);

echo_srv(conn);

exit(EXIT_SUCCESS);

}

else

close(conn);

}

return 0;

}

echocli2.c

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#define ERR_EXIT(m) \

do \

{ \

perror(m); \

exit(EXIT_FAILURE); \

} while(0)

ssize_t readn(int fd, void *buf, size_t count)

{

size_t nleft = count;

ssize_t nread;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nread = read(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nread == 0)

return count - nleft;

bufp += nread;

nleft -= nread;

}

return count;

}

ssize_t writen(int fd, const void *buf, size_t count)

{

size_t nleft = count;

ssize_t nwritten;

char *bufp = (char*)buf;

while (nleft > 0)

{

if ((nwritten = write(fd, bufp, nleft)) < 0)

{

if (errno == EINTR)

continue;

return -1;

}

else if (nwritten == 0)

continue;

bufp += nwritten;

nleft -= nwritten;

}

return count;

}

ssize_t recv_peek(int sockfd, void *buf, size_t len)

{

while (1)

{

int ret = recv(sockfd, buf, len, MSG_PEEK);

if (ret == -1 && errno == EINTR)

continue;

return ret;

}

}

ssize_t readline(int sockfd, void *buf, size_t maxline)

{

int ret;

int nread;

char *bufp = buf;

int nleft = maxline;

while (1)

{

ret = recv_peek(sockfd, bufp, nleft);

if (ret < 0)

return ret;

else if (ret == 0)

return ret;

nread = ret;

int i;

for (i=0; i<nread; i++)

{

if (bufp[i] == ‘\n‘)

{

ret = readn(sockfd, bufp, i+1);

if (ret != i+1)

exit(EXIT_FAILURE);

return ret;

}

}

if (nread > nleft)

exit(EXIT_FAILURE);

nleft -= nread;

ret = readn(sockfd, bufp, nread);

if (ret != nread)

exit(EXIT_FAILURE);

bufp += nread;

}

return -1;

}

void echo_cli(int sock)

{

char sendbuf[1024] = {0};

char recvbuf[1024] = {0};

while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)

{

writen(sock, sendbuf, strlen(sendbuf));

int ret = readline(sock, recvbuf, sizeof(recvbuf));

if (ret == -1)

ERR_EXIT("readline");

else if (ret == 0)

{

printf("client close\n");

break;

}

fputs(recvbuf, stdout);

memset(sendbuf, 0, sizeof(sendbuf));

memset(recvbuf, 0, sizeof(recvbuf));

}

close(sock);

}

int main(void)

{

int sock[5];

int i;

for (i=0; i<5; i++)

{

if ((sock[i] = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)

ERR_EXIT("socket");

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(sock[i], (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

ERR_EXIT("connect");

struct sockaddr_in localaddr;

socklen_t addrlen = sizeof(localaddr);

if (getsockname(sock[i], (struct sockaddr*)&localaddr, &addrlen) < 0)

ERR_EXIT("getsockname");

printf("ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr), ntohs(localaddr.sin_port));

}

echo_cli(sock[0]);

return 0;

}

makefile:

.PHONY:clean all

CC=gcc

CFLAGS=-Wall -g

BIN=echosrv echocli echocli2

all:$(BIN)

%.o:%.c

$(CC) $(CFLAGS) -c $< -o [email protected]

clean:

rm -f *.o $(BIN)

socket编程中recv与send函数

时间: 2024-10-29 19:07:58

socket编程中recv与send函数的相关文章

socket编程中write、read和send、recv之间的区别

http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立好了tcp连接之后,我们就可以把得到的fd当作文件描述符来使用. 由此网络程序里最基本的函数就是read和write(int fd, const void*buf,size_t nbytes); write的返回值大于0,表示写了部分或者是全部的数据. 这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新.也就是说,网络写函数

socket编程中最常用的几个数据类型和转换函数

高位字节优先和低位字节优先.Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换. 第一个结构类型是:struct sockaddr 该类型是用来保存socket信息的 struct sockaddr {   unsigned short sa_family;   /* 地址族, AF_xxx */   char sa_data[14];  /* 14 字节的协议地址 */ }; sa_family一

Socket编程时recv函数错误:Transport endpoint is not connected的解决

今天在做socket网络通信实验时,server端执行到recv函数处报错:Transport endpoint is not connected. 以下是server和client的源码: server.c 1 #include <stdio.h> 2 #include <arpa/inet.h> 3 #include <sys/socket.h> 4 #include <string.h> 5 #include <unistd.h> 6 #i

IP地址的三种表示格式及在Socket编程中的应用

转自:http://blog.csdn.net/hguisu/article/details/7449955 使用TCP/IP协议进行网络应用开发的朋友首先要面对的就是对IP地址信息的处理.IP地址其实有三种不同的表示格式:  1)Ascii(网络点分字符串)-        2) 网络地址(32位无符号整形,网络字节序,大头)        3)主机地址 (主机字节序)   IP地址是IP网络中数据传输的依据,它标识了IP网络中的一个连接,一台主机可以有多个IP地址,IP分组中的IP地址在网络

TCP中 recv和sendf函数

recv和send函数: #include<sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); ssize_t recv(int sockfd, const void *buff, size_t nbytes, int flags); flags的值中 MSG_OOB和MSG_PEEK比较重要. read和recv函数的区别在于: read函数读取缓冲区的数据之后,会将缓冲区的数据删除,而r

C#函数式编程中的标准高阶函数详解

何为高阶函数 大家可能对这个名词并不熟悉,但是这个名词所表达的事物却是我们经常使用到的.只要我们的函数的参数能够接收函数,或者函数能够返回函数,当然动态生成的也包括在内.那么我们就将这类函数叫做高阶函数.但是今天我们的标题并不是高阶函数,而是标准高阶函数,既然加上了这个标准,就意味着在函数式编程中有一套标准的函数,便于我们每次调用.而今天我们将会介绍三个标准函数,分别为Map.Filter.Fold. Map 这个函数的作用就是将列表中的每项从A类型转换到B类型,并形成一个新的类型.下面我们可以

SO_REUSEPORT和SO_REUSEADDR与socket编程中那些关于内核自动分配的...

前言: 本文分为三个章节,第一个章节主要是翻译总结汇总一位国外的老兄在Stack Overflow上的回答,但实际上Linux发展这么多年,文中的知识点已经过时且不准确了, 在第二章中通过实验,有更加准确的描述.但是,第一章节也不是全然无用,至少在了解SO_REUSEPORT和SO_REUSEADDR的发展上是有帮助的. 在第三章节中,做实验过程中需要验证一些其他的知识点,因此在这里做一个汇总. wxy:其实就是我研究完才发现文章写的不对,又不想浪费自己的研究成果,哈哈哈哈哈,hianghian

网络编程中shut_down和close()函数的区别

在Linux C网络编程中,一共有两种方法来关闭一个已经连接好的网络通信,它们就是close函数和shutdown函数,它们的函数原型分别为: 1 #include<unistd.h> 2 int close(int sockfd) 3 //返回:0--成功, 1--失败 4   5 #include<sys/socket.h> 6 int shutdown(int sockfd, int howto) 7 //返回:0--成功, 1--失败 对一个tcp socket调用clos

Socket编程中,阻塞与非阻塞的区别

阻塞:一般的I/O操作可以在新建的流中运用.在服务器回应前它等待客户端发送一个空白的行.当会话结束时,服务器关闭流和客户端socket.如果在队列中没有请示将会出现什么情况呢?那个方法将会等待一个的到来.这个行为叫阻塞.accept()方法将会阻塞服务器线程直到一个呼叫到来.当5个连接处理完闭之后,服务器退出.任何的在队列中的呼叫将会被取消. 非阻塞:非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回.比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,