,,用C语言进行最基本的socket编程

,,用C语言进行最基本的socket编程

本文主要介绍了C语言中socket编程的基础知识,包括最基本的客户端发送和服务器接收数据的实现。有需要的朋友可以参考一下。

什么是插座?

你经常听到人们谈论“插座”,也许你不知道它的确切含义。现在让我告诉你:它是一种通过使用标准Unix文件描述符与其他程序通信的方法。什么?你可能听过一些Unix黑客说,“啊,Unix中的一切都是文件!”那个家伙可能在谈论这样一个事实,当一个Unix程序执行任何形式的I/O时,这个程序都在读或写一个文件描述符。文件描述符只是一个与打开的文件相关联的整数。然而,这个文件可能是网络连接、FIFO、管道、终端、磁盘上的文件或其他东西。Unix中的一切都是文件!所以,当你想与互联网上的其他程序通信时,你需要使用文件描述符。你必须明白你刚才说的话。现在你可能会想,“那么我从哪里获得网络通信的文件描述符呢?”反正我要回答这个问题:你用系统调用socket(),系统返回socket描述符,然后你通过它进行send()和recv()调用。“但是……”,你可能会有很大的疑惑。"如果是文件描述符,为什么不调用read()和write()进行套接字通信?"简单的回答就是:“可以用!”。详细的回答是:“可以,但是使用send()和recv()可以更好地控制数据传输。”有这样一种情况:在我们的世界里,插座有很多种。有DARPA互联网地址(互联网套接字)、本地节点路径名(Unix套接字)、CCITT X.25地址(可以完全忽略X.25套接字)。也许在你的Unix机器上还有其他的。这里只说第一个:互联网插座。

两种类型的互联网插座:

你什么意思?互联网插座有两种?是的不,我在撒谎。其实还有很多,只是不想吓到你。这里只说两种。除了这些,我打算另外介绍的‘Raw Sockets’也很强大,值得参考。

那么这两种类型是什么呢?一个是“流套接字”(流格式),另一个是“数据报套接字”(包格式)。以后讲到' SOCK_STREAM '和' SOCK_DGRAM '我们也会用到。数据套接字有时被称为“无连接套接字”(如果你真的想连接,可以使用connect()。流式套接字是一种可靠的双向通信数据流。如果你按顺序向套接字输出“1,2”,那么它们会按顺序“1,2”到达另一端。它们交付时没有错误,并且有自己的错误控制,这里就不讨论了。

什么是使用流式套接字?你可能听说过telnet,是吗?它使用流式套接字。您需要输入的字符按顺序到达,不是吗?同样,WWW浏览器使用的HTTP协议也使用它们来下载页面。事实上,当你通过80端口telnet到一个WWW站点,然后输入“GET pagename”,你也可以获得HTML内容。为什么流式套接字可以实现高质量的数据传输?这是因为它使用“传输控制协议”,也称为“TCP”(详情请参考RFC-793。)TCP控制你的数据按顺序到达,没有错误。

错误。可能你听到“TCP”是因为你听到了“TCP/IP”。这里的IP指的是“互联网协议”(请参考RFC-791。)IP只是处理互联网路由。

数据报套接字呢?为什么叫无连接?为什么不靠谱?有一些事实:如果你发送一个数据报,它可能会到达,它可能会出现故障。如果它到达,那么在这个包裹里面没有错误。数据报也使用IP进行路由,但它不使用TCP。它使用用户数据报协议,也称为UDP(请参考RFC-768。)

为什么它们是断开的?主要是因为它不像streaming socket那样维护连接。您只需构建一个数据包,用目标信息构建一个IP报头,然后将它发送出去。不需要连接。它们通常用于传输数据包到数据包的信息。简单的应用有tftp,bootp等等。

你可能会想,“如果数据丢失了,这些程序怎么能正常工作呢?”我的朋友,每个程序在UDP上都有自己的协议。比如tftp协议发送的每一个包都被接受,接收方必须发回一个包说“我收到了!”(“命令正确响应”也称为“ACK”数据包)。如果发送方在一定时间内(如5秒)没有收到应答,它将重新发送应答,直到收到ACK。在实现SOCK_DGRAM应用程序时,这个ACK过程非常重要。

简单的发送和接收实现

服务器接收代码:

#包含Winsock2.h

#pragma注释(lib,' Ws2_32.lib ')

#包含stdio.h

#包含内存. h

void main()

{

WSAData wsd

WSAStartup(MAKEWORD(2,0),wsd);

套接字s=NULL

s=socket(AF_INET,SOCK_STREAM,IP proto _ TCP);

struct sockaddr _ in ch

memset(ch,0,sizeof(ch));

ch.sin _ family=AF _ INET

ch . sin _ addr . s _ addr=in addr _ ANY;

ch . sin _ port=htons(1041);

int b=bind(s,(struct sockaddr *) ch,sizeof(ch));

#定义队列大小5

int l=listen(s,QUEUE _ SIZE);

Printf('正在监听本机的1041端口!\ n’);

SOCKET sc=accept(s,0,0);

Printf('客户端已经连接到本机的1041端口!\ n’);

#定义BUF_SIZE 4096

int rece byt=0;

while(1)

{

char BUF[BUF _ SIZE];

receByt=recv(sc,buf,BUF_SIZE,0);

buf[rece byt]=' \ 0 ';

if(rece by 0)

{

Printf('收到的消息是:%s\n ',buf);

}

其他

{

Printf('接收消息结束!');

打破;

}

}

int IC=close socket(sc);

int is=close socket(s);

}

客户端发送的代码:

#包含Winsock2.h

#pragma注释(lib,' Ws2_32.lib ')

#包含stdio.h

#包含内存. h

#包含字符串. h

void main()

{

WSAData wsd

WSAStartup(MAKEWORD(2,0),wsd);

套接字s=NULL

s=socket(AF_INET,SOCK_STREAM,IP proto _ TCP);

struct sockaddr _ in ch

memset(ch,0,sizeof(ch));

ch.sin _ family=AF _ INET

ch . sin _ addr . s _ addr=inet _ addr(' 127 . 0 . 0 . 1 ');

ch . sin _ port=htons(1041);

int c=connect(s,(struct sockaddr *) ch,sizeof(ch));

Printf('已经连接到服务器的1041端口!现在您可以向服务器发送消息了!\ n’);

#定义BUF_SIZE 4096

char info[1024],BUF[BUF _ SIZE];

while(1)

{

获取(信息);

if(info[0]=='\0 ')

打破;

strcpy(buf,info);

int nsend=send(s,buf,strlen(buf),0);

}

int IC=close socket(s);

}

代码已经优化,集成了多线程。接收和发送放在同一个文件中,通过参数方式调用发送和接收模块。增加了s句柄(或对象)来判断创建socket时返回值是否为invalid _ SOCKET,SOCKET绑定操作的返回值是否为SOCKET_ERROR。其他socket操作也要判断SOCKET_ERROR,这样才能保证程序的稳定性。在这里,只是测试代码,所以不要写那么多,剩下的就看你自己了。

#包含Winsock2.h

#pragma注释(lib,' Ws2_32.lib ')

#包含stdio.h

#包含内存. h

#包含字符串. h

#include pthread.h

void Receive();

void Send();

void creat thread();

套接字s=NULL

pthread _ t t[1000];

int thread count=0;

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

{

Printf('本项目学号:713901040041 \ n ');

Printf('程序描述:服务器和客户端是同一个程序,请用不同的参数运行。\ n’);

Printf ('receiver请使用r参数;请对发送方使用s参数。\ n’);

//printf('len : %d\n ',argc);

//printf('count %d\n ',argc);

//printf('value: %s\n ',argv[1]);

//printf('%d ',argv[1][0]==' r ');

如果(argc=1)

{

printf('请输入程序参数.\ n’);

退出(0);

}

if(argc1 argv[1][0]=='r ')

{

printf('运行接收.\ n’);

receive();

}

if(argc1 argv[1][0]=='s ')

{

printf('运行发送.\ n’);

send();

}

}

void* receiveWork(void * args)

{

SOCKET sc=accept(s,0,0);

if(sc==INVALID_SOCKET)

{

printf('sc错误');

}

创建线程();

printf(' -客户端已经连接到本机的%d线程连接!\n ',线程计数-2);

#定义BUF_SIZE 4096

int rece byt=0;

while(1)

{

char BUF[BUF _ SIZE];

receByt=recv(sc,buf,BUF_SIZE,0);

buf[rece byt]=' \ 0 ';

如果(接收0)

{

printf('线程接收的消息是:%s\n ',buf);

}

其他

{

printf('客户端已退出,');

打破;

}

}

int IC=关闭套接字(sc);

printf('服务器结束连接!\ n’);

返回空

}

void creatThread()

{

pthread_create(t[threadCount ],NULL,receiveWork,NULL);

}

无效接收()

{

WSAData wsd

WSAStartup(MAKEWORD(2,0),wsd);

s=socket(AF_INET,SOCK_STREAM,IP proto _ TCP);

if(s==INVALID_SOCKET)

{

printf("套接字创建错误");

}

结构sockaddr _ in ch

memset(ch,0,sizeof(ch));

ch.sin _ family=AF _ INET

栗色sin _ addr。s _ addr=in addr _ ANY

栗色sin _ port=htons(1041);

int b=bind(s,(struct sockaddr *) ch,sizeof(ch));

if(b==套接字_错误)

{

printf('绑定失败,出错代码是:%d\n ',WSAGetLastError());

退出(0);

}

#定义队列大小5

int l=listen(s,QUEUE _ SIZE);

printf('正在监听本机的1041端口!\ n’);

创建线程();

for(int I=0;i1000我)

{

pthread_join(t[i],NULL);

}

int is=关闭套接字;

}

空的发送()

{

WSAData wsd

WSAStartup(MAKEWORD(2,0),wsd);

套接字s=空

s=socket(AF_INET,SOCK_STREAM,IP proto _ TCP);

if(s==INVALID_SOCKET)

{

printf("套接字创建错误");

}

结构sockaddr _ in ch

memset(ch,0,sizeof(ch));

ch.sin _ family=AF _ INET

栗色sin _ addr。s _ addr=inet _ addr(' 127。0 .0 .1 ');

栗色sin _ port=htons(1041);

int c=connect(s,(struct sockaddr *) ch,sizeof(ch));

printf('已经连接到服务器的1041端口!现在可以向服务器发送消息了!\ n’);

#定义BUF_SIZE 4096

char info[1024],BUF[BUF _ SIZE];

while(1)

{

获取(信息);

if(info[0]=='\0 ')

打破;

strcpy(buf,info);

int nsend=send(s,buf,strlen(buf),0);

}

int IC=关闭套接字;

}

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: