socket函数 linux?socket send函数返回值

大家好,关于socket函数 linux很多朋友都还不太明白,今天小编就来为大家分享关于socket send函数返回值的知识,希望对各位有所帮助!

Windows Socket和Linux Socket编程的区别

SOCKET在原理上应该是一样的,只是不同系统的运行机置有些不同。

Socket编程 windows到Linux代码移植遇到的问题

1、一些常用函数的移植

2、网络

socket相关程序从windows移植到linux下需要注意的

1)头文件

windows下winsock.h/winsock2.h

linux下sys/socket.h

错误处理:errno.h

其他常用函数的头文件可到命令行下用man指令查询。

2)初始化

windows下需要用WSAStartup

linux下不需要(很方便),直接可以使用

3)关闭socket

windows下closesocket(...)

linux下close(...)

4)类型

windows下SOCKET

在linux下为int类型

5)绑定地址的结构体

名称相同,都是struct sockaddr、struct sockaddr_in,这两者通常转换使用;

在Windows下面名称都是大写,而在Linux下为小写

常用:

Linux下:

sockaddr_in destAddr;

destAdd.sin_family=AF_INET;

destAddr.sin_port=htons(2030);

destAddr.sin_addr.s_addr=inet_addr("192.168.1.1");

Windows下:

SOCKADDR_IN destAddr;

destAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.1");

但结构体中成员的名称不同

Windows中结构体成员

struct sockaddr_in{

short sin_family;

u_short sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};

struct sockaddr{

u_short sa_family;

char sa_data[14];

};

struct in_addr{

union{

struct{ u_char s_b1,s_b2,s_b3,s_b4;} S_un_b;

struct{ u_short s_w1,s_w2;} S_un_w;

u_long S_addr;

} S_un;

};

下面的一些宏可以使windows下的程序移植到linux下(通过类型的重新定义,使代码具有linux和windows下的移植性)

[cpp] view plaincopy

#ifdef WIN32

typedef int socklen_t;

typedef int ssize_t;

#endif

#ifdef __LINUX__

typedef int SOCKET;

typedef unsigned char BYTE;

typedef unsigned long DWORD;

#define FALSE 0

#define SOCKET_ERROR(-1)

#endif

[cpp] view plaincopy

#ifdef WIN32

typedef int socklen_t;

typedef int ssize_t;

#endif

#ifdef __LINUX__

typedef int SOCKET;

typedef unsigned char BYTE;

typedef unsigned long DWORD;

#define FALSE 0

#define SOCKET_ERROR(-1)

#endif

6)获取错误码

windows下getlasterror()/WSAGetLastError()

linux下errno变量

7)设置非阻塞

windows下ioctlsocket()

linux下fcntl()<fcntl.h>

8)send函数最后一个参数

windows下一般设置为0

linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可能会导致程序退出。

9)毫秒级时间获取

windows下GetTickCount()

linux下gettimeofday()

10)数据类型的一些转化

通用的:

小端到大端(网络协议使用)的转换:htonl, htons

点分十进制IP和整数之间的相互转换:inet_addr()(该函数将点分十进制转为整数),inet_aton(),inet_ntoa(),inet_pton()(linux下独有该函数可以实现相互之间的转换)

使用到的头文件不相同,linux下用man命令查询。

另外注意:

linux下使用的套接字为伯克利套接字,因此在select()函数的使用上(第一个参数的设置)也有区别;

windows下为了与伯克利套接字匹配,第一个参数是无所谓,一般可设为0;

int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!

3、多线程

多线程:(win)process.h--〉(linux)pthread.h

_beginthread--> pthread_create

_endthread--> pthread_exit

socket linux c++ send()函数

给你一个代码,linux下编译运行即可,做了简单的注释,client.c如下:

send()函数在client.c末尾

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<errno.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#defineMAXLINE4096//发送接受信息长度

#definePORT6666//端口

intmain(intargc,char**argv)

{

intsockfd,n;

charrecvline[MAXLINE],sendline[MAXLINE];

structsockaddr_inservaddr;

if(argc!=2){

printf("usage:./client<ipaddress>\n");//使用方法

exit(0);

}

if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){//创建套接字,并未连接

printf("createsocketerror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

//memset(结构体地址,清零,要清零的长度);清零结构体servaddr,将结构体数据全部设置为0

//同bzero(结构体地址,要清理的长度);默认清零

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

servaddr.sin_family=AF_INET;//sa_family是通信类型,最常用的值是"AF_INET"

servaddr.sin_port=htons(PORT);//端口号

//servaddr.sin_addr.s_addr=inet_addr(argv[1]);//服务器IP,如下功能相同

if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0){

printf("inet_ptonerrorfor%s\n",argv[1]);

exit(0);

}

//连接服务器

if(connect(sockfd,(structsockaddr*)&servaddr,sizeof(servaddr))<0){

printf("connecterror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

printf("sendmsgtoserver:\n");

fgets(sendline,MAXLINE,stdin);//输入向服务器发送的信息

if(send(sockfd,sendline,strlen(sendline),0)<0)//向服务器发送信息

{

printf("sendmsgerror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

close(sockfd);//关闭套接字

exit(0);

}

服务器程序:server.c如下:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<errno.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#defineMAXLINE4096

#definePORT6666

intmain(intargc,char**argv)

{

intlistenfd,connfd;

structsockaddr_inservaddr;

charbuff[MAXLINE];

intn;

if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){//创建套接字

printf("createsocketerror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

memset(&servaddr,0,sizeof(servaddr));//结构体清零

servaddr.sin_family=AF_INET;//sa_family是通信类型,最常用的值是"AF_INET"

servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//指定接受任何连接

servaddr.sin_port=htons(PORT);//监听端口

//给套接口绑定地址

if(bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr))==-1){

printf("bindsocketerror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

if(listen(listenfd,10)==-1){//开始监听,最大请求数为10,可以自己设置

printf("listensocketerror:%s(errno:%d)\n",strerror(errno),errno);

exit(0);

}

printf("======waitingforclient'srequest======\n");

while(1){

//建立通信,等待客户端connect()函数的连接

if((connfd=accept(listenfd,(structsockaddr*)NULL,NULL))==-1)

{

printf("acceptsocketerror:%s(errno:%d)",strerror(errno),errno);

continue;

}

n=recv(connfd,buff,MAXLINE,0);//n可以判断错误,此处可直接用recv()函数

//接收到的信息存放在buff中

buff[n]='\0';//添加结束符

printf("recvmsgfromclient:%s\n",buff);

close(connfd);

}

close(listenfd);

}

Linux C中的Socket,shutdown函数和close函数有什么不同

假设server和client已经建立了连接,server调用了close,发送FIN段给client(其实不一定会发送FIN段,后面再说),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN段会返回0,但client此时还是可以write给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。有时候代码中需要连续多次调用write,可能还来不及调用read得知对方已关闭了连接就被SIGPIPE信号终止掉了,这就需要在初始化时调用sigaction处理SIGPIPE信号,对于这个信号的处理我们通常忽略即可,signal(SIGPIPE, SIG_IGN);如果SIGPIPE信号没有导致进程异常退出,write返回-1并且errno为EPIPE。#include intclose(int fd);close关闭了自身数据传输的两个方向。#include intshutdown(int sockfd, int how);shutdown可以选择关闭某个方向或者同时关闭两个方向,shutdownhow= 1 or how= 2(SHUT_WR or SHUT_RDWR),可以保证对等方接收到一个EOF字符(即发送了一个FIN段),而不管其他进程是否已经打开了这个套接字。而close不能保证,只有当某个sockfd的引用计数为0,close才会发送FIN段,否则只是将引用计数减1而已。也就是说只有当所有进程(可能fork多个子进程都打开了这个套接字)都关闭了这个套接字,close才会发送FIN段。所以说,如果是调用shutdown how= 1,则意味着往一个已经接收FIN的套接字中写是允许的,接收到FIN段仅代表对方不再发送数据,但对方还是可以读取数据的,可以让对方可以继续读取缓冲区剩余的数据。下面使用shutdown修改客户端程序,在前面讲过的使用select函数修改后的客户端程序基础上,修改很小一部分:C++ Codeif(FD_ISSET(fd_stdin,&rset)){if(fgets(sendbuf, sizeof(sendbuf), stdin)== NULL){stdineof= 1;//表示已经输入完毕/*关闭sock的写端,还能够接收数据,在sock的缓冲区末尾添加一个FIN段*/shutdown(sock, SHUT_WR);}else{writen(sock, sendbuf, strlen(sendbuf));memset(sendbuf, 0, sizeof(sendbuf));}}为了测试我们想要的效果,需要在select函数修改后的服务器端程序的 134行代码之后,即writen之前 sleep(4);目的是接收到客户端数据后不马上回射回去,睡眠4s后在客户端已经关闭连接的情况下再发送数据。先运行服务器端程序,再运行客户端程序,在客户端标准输入,迅速敲入两行:AAAAA

BBBBB

然后按下ctrl+d即fgets会返回NULL,然后调用shutdown关闭写端,虽然服务器端延时才发送数据,此时客户端写端已经关闭,但还是可以读取到回射回来的数据,服务器端最后得到一个FIN段,read返回0,打印输出 client close,并且close(conn);而客户端在读取服务端回射回来的两次数据后,再次read也返回0,故打印 server connectclose,break退出循环,进程顺利退出。从下面的输出还可以看出,因为延时的关系,所以不像以前那样发射一行就回射一行。simba@ubuntu:~/Documents/code/linux_programming/UNP/socket$./echoser_selectrecv connect ip=127.0.0.1 port=54010fdsgfgdgfedgclient close...........................simba@ubuntu:~/Documents/code/linux_programming/UNP/socket$./echocli_select_shutdownlocal ip=127.0.0.1 port=54010fdsgfgdgfedgfdsgfgdgfedg1gfedgserver connect close如果我们将客户端程序中的shutdown改成了 close,那么当延时后服务器端发送数据给客户端时,客户端的读端和写端都已经关闭,第一次发AAAAA会返回一个RST段,根据本文前面所说,再次发BBBBB直接产生SIGPIPE信号,默认会终止进程,但因为我们已经设置了忽略SIGPIPE信号,所以服务器端进程不会被终止,但客户端也会出错,因为回到while循环开头,select阻塞等待时发现套接字的读端已经关闭,所以不能再关心可读事件了,select会返回-1,错误码是 EBADF: Bad File Descriptor。Linux C中的Socket,shutdown函数和close函数有什么不同

阅读剩余
THE END