linux socket() 函数 linux怎么打开软件
这篇文章给大家聊聊关于linux socket() 函数,以及linux怎么打开软件对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
socket编程在windows和linux下的区别
下面大概分几个方面进行罗列:
Linux要包含
[cpp]
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<arpa/inet.h>
等头文件,而windows下则是包含
[cpp]
#include<winsock.h>
。
Linux中socket为整形,Windows中为一个SOCKET。
Linux中关闭socket为close,Windows中为closesocket。
Linux中有变量socklen_t,Windows中直接为int。
因为linux中的socket与普通的fd一样,所以可以在TCP的socket中,发送与接收数据时,直接使用read和write。而windows只能使用recv和send。
设置socet选项,比如设置socket为非阻塞的。Linux下为
[cpp]
flag= fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flag| O_NONBLOCK);
,Windows下为
[cpp]
flag= 1;
ioctlsocket(fd, FIONBIO,(unsigned long*)&flag);
。
当非阻塞socket的TCP连接正在进行时,Linux的错误号为EINPROGRESS,Windows的错误号为WSAEWOULDBLOCK。
file
Linux下面,文件换行是"\n",而windows下面是"\r\n"。
Linux下面,目录分隔符是"/",而windows下面是"\"。
Linux与Windows下面,均可以使用stat调用来查询文件信息。但是,Linux只支持2G大小,而Windows只支持4G大小。为了支持更大的文件查询,可以在Linux环境下加
_FILE_OFFSET_BITS=64定义,在Windows下面使用_stat64调用,入参为struct __stat64。
Linux中可根据stat的st_mode判断文件类型,有S_ISREG、S_ISDIR等宏。Windows中没有,需要自己定义相应的宏,如
[cpp]
#define S_ISREG(m)(((m)& 0170000)==(0100000))
#define S_ISDIR(m)(((m)& 0170000)==(0040000))
Linux中删除文件是unlink,Windows中为DeleteFile。
time
Linux中,time_t结构是长整形。而windows中,time_t结构是64位的整形。如果要在windows始time_t为32位无符号整形,可以加宏定义,_USE_32BIT_TIME_T。
Linux中,sleep的单位为秒。Windows中,Sleep的单位为毫秒。即,Linux下sleep(1),在Windows环境下则需要Sleep(1000)。
Windows中的timecmp宏,不支持大于等于或者小于等于。
Windows中没有struct timeval结构的加减宏可以使用,需要手动定义:
[cpp]
#define MICROSECONDS(1000* 1000)
#define timeradd(t1, t2, t3) do{\
(t3)->tv_sec=(t1)->tv_sec+(t2)->tv_sec;\
(t3)->tv_usec=(t1)->tv_usec+(t2)->tv_usec% MICROSECONDS;\
if((t1)->tv_usec+(t2)->tv_usec> MICROSECONDS)(t3)->tv_sec++;\
} while(0)
#define timersub(t1, t2, t3) do{\
(t3)->tv_sec=(t1)->tv_sec-(t2)->tv_sec;\
(t3)->tv_usec=(t1)->tv_usec-(t2)->tv_usec;\
if((t1)->tv_usec-(t2)->tv_usec< 0)(t3)->tv_usec--,(t3)->tv_usec+= MICROSECONDS;\
} while(0)
调用进程
Linux下可以直接使用system来调用外部程序。Windows最好使用WinExec,因为WinExec可以支持是打开还是隐藏程序窗口。用WinExec的第二个入参指明,如
SW_SHOW/SW_HIDE。
杂项
Linux为srandom和random函数,Windows为srand和rand函数。
Linux为snprintf,Windows为_snprintf。
同理,Linux中的strcasecmp,Windows为_stricmp。
错误处理
Linux下面,通常使用全局变量errno来表示函数执行的错误号。Windows下要使用GetLastError()调用来取得。
Linux环境下仅有的
这些函数或者宏,Windows中完全没有,需要用户手动实现。
atoll
[cpp]
long long
atoll(const char*p)
{
int minus= 0;
long long value= 0;
if(*p=='-')
{
minus++;
p++;
}
while(*p>='0'&&*p<='9')
{
value*= 10;
value+=*p-'0';
p++;
}
return minus? 0- value: value;
}
gettimeofday
[cpp]
#if defined(_MSC_VER)|| defined(_MSC_EXTENSIONS)
#define EPOCHFILETIME 11644473600000000Ui64
#else
#define EPOCHFILETIME 11644473600000000ULL
#endif
struct timezone
{
int tz_minuteswest;
int tz_dsttime;
};
int
gettimeofday(struct timeval*tv, struct timezone*tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
if(tv)
{
GetSystemTimeAsFileTime(&ft);
li.LowPart= ft.dwLowDateTime;
li.HighPart= ft.dwHighDateTime;
t= li.QuadPart;/* In 100-nanosecond intervals*/
t-= EPOCHFILETIME;/* Offset to the Epoch time*/
t/= 10;/* In microseconds*/
tv->tv_sec=(long)(t/ 1000000);
tv->tv_usec=(long)(t% 1000000);
}
if(tz)
{
if(!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest= _timezone/ 60;
tz->tz_dsttime= _daylight;
}
return 0;
}
编译相关
当前函数,Linux用__FUNCTION__表示,Windows用__func__表示。
--------------------------------------------------------------------------------
Socket编程 windows到Linux代码移植遇到的问题
1)头文件
windows下winsock.h/winsock2.h
linux下sys/socket.h
错误处理:errno.h
2)初始化
windows下需要用WSAStartup
linux下不需要
3)关闭socket
windows下closesocket(...)
linux下close(...)
4)类型
windows下SOCKET
linux下int
如我用到的一些宏:
#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
5)获取错误码
windows下getlasterror()/WSAGetLastError()
linux下errno变量
6)设置非阻塞
windows下ioctlsocket()
linux下fcntl()<fcntl.h>
7)send函数最后一个参数
windows下一般设置为0
linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可能会导致程序退出。
8)毫秒级时间获取
windows下GetTickCount()
linux下gettimeofday()
3、多线程
多线程:(win)process.h--〉(linux)pthread.h
_beginthread--> pthread_create
_endthread--> pthread_exit
-----------------------------------------------------------------
windows与linux平台使用的socket均继承自Berkeley socket(rfc3493),他们都支持select I/O模型,均支持使用getaddrinfo与getnameinfo实现协议无关编程。但存在细微差别,
主要有:
头文件及类库。windows使用winsock2.h(需要在windows.h前包含),并要链接库ws2_32.lib;linux使用netinet/in.h, netdb.h等。
windows下在使用socket之前与之后要分别使用WSAStartup与WSAClean。
关闭socket,windows使用closesocket,linux使用close。
send*与recv*函数参数之socket长度的类型,windows为int,linux为socklen_t,可预编译指令中处理这一差异,当平台为windows时#define socklen_t unsigned int。
select函数第一个参数,windows忽略该参数,linux下该参数表示集合中socket的上限值,一般设为sockfd(需select的socket)+ 1。
windows下socket函数返回值类型为SOCKET(unsigned int),其中发生错误时返回INVALID_SOCKET(0),linux下socket函数返回值类型int,发生错误时返回-1。
另外,如果绑定本机回环地址,windows下sendto函数可以通过,linux下sendto回报错:errno=22, Invalid arguement。一般情况下均绑定通配地址。
转载jlins
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函数有什么不同