socket linux c socket下载

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函数有什么不同

计算机网络socket linux下用c或c++写

我这有一段最简单的SOCKET连接服务端的~!前阵子装Ubuntu 10后写着实验用的,这是最基本的TCP服务端框架。各种函数的条用跟 WINDOWS下的一样(我说的WINDOWS下可不是MFC喔~!)客户端自己琢磨,不懂的话再发你~!至于你要的细节,我感觉还是自己写的好

人不能太懒~!必须深入认识否则你领略不到 C程序设计的精髓~!

//////////代码如下//////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////

///////////////////////// H*F*W 2010.05.21 In GuangZhou///////////////////////////

///////////////////////// LINUX SOCKET实验最简单服务端///////////////////////////

/////////////////////// linux编程 SOCKET,GTK有共同兴趣的朋友+我 Q: 176469428////////

#include<stdio.h>

#include<string.h>

#include<sys/socket.h>

#include<netinet/in.h>

int Hlisten(unsigned short hport)

{

int hsock,rhsock,cc,alen,ret;

struct sockaddr_in hlsock;

char hbuf[65535];

if((hsock=socket(AF_INET,SOCK_STREAM,0))==-1){printf("Error in socket()\n");return 0;}//建立套接字

memset(&hlsock,0,sizeof(hlsock));//初始化SOCKET空间

hlsock.sin_family=AF_INET;

hlsock.sin_port=htons(hport);///监听端口

hlsock.sin_addr.s_addr=htonl(INADDR_ANY);///地址族

ret=1;

setsockopt(hsock,SOL_SOCKET,SO_REUSEADDR,&ret,sizeof(ret));

if(bind(hsock,(struct sockaddr*)&hlsock,sizeof(hlsock))==-1){printf("Error in bind()\n");return 0;}//帮定

if(listen(hsock,0)==-1){printf("Error in listen()\n");return 0;}///进入监听状态

alen=sizeof(hlsock);

rhsock=accept(hsock,(struct sockaddr*)&hlsock,&alen);///接受客户端接入

while(1)

{

memset(hbuf,0,sizeof(hbuf));

cc=recv(rhsock,hbuf,sizeof(hbuf),0);///等待接收数据

if(cc==-1)break;

printf("%s",hbuf);///显示接收内容

}

close(hsock);//关闭连接

return 0;

}

int main(int argc,char*argv[])

{

//if(argc<=1){printf("usge: [port]");return 0;}

Hlisten(330);//调用监听过程传入监听端口

return 0;

}

///////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////

//////////////////使用gcc编译直接就可以看到效果////////////////

/////////////////////////////////////////////////////////////////

Linux C/C++ UDP socket通信

Linux C/C++进行UDP socket通信时,其Server端与Client端的主要流程各有不同。Server端流程包括初始化socket,绑定端口与地址,接收数据并处理后,发送回应至客户端。而Client端则需要创建socket,获取Server地址与端口信息,接着发送请求数据,接收Server回应。

在进行UDP通信时,需用到四个关键API,分别是socket(),bind(),sendto()与recvfrom()。掌握这四个函数,便能熟练地利用UDP进行各种数据传输。

在UDP通信中,地址与端口的配置是通过sockaddr_in结构体来完成的。该结构体包括了IP地址、端口号、网络字节序等信息,便于程序准确地设置与识别通信目标。

具体来说,消息的发送与接收主要通过sendto()与recvfrom()函数来完成。sendto()函数用于发送数据包至指定目标,而recvfrom()则用于接收从任意地址发送来的数据包。这两个函数的使用,使得UDP通信在灵活性与效率上都有了显著提升。

为了验证上述流程与函数的正确性,通常会编写测试程序。Server端程序会监听特定端口,接收客户端发送的数据,并进行处理后将回应发回。同时,Client端程序则会尝试连接Server端并发送测试数据,接收Server的回应,以此测试通信的稳定性和数据传输的正确性。

阅读剩余
THE END