编写socket套接字的步骤 实现套接字编程接口的两种方式
2024-11-10 09:55 - 立有生活网
简述Socket(套接字)通信
所谓Socket就是套接字,套接字就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
编写socket套接字的步骤 实现套接字编程接口的两种方式
编写socket套接字的步骤 实现套接字编程接口的两种方式
编写socket套接字的步骤 实现套接字编程接口的两种方式
一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。
一、Socket(套接字):
Socket(套接字)是通信的基石,是支持TCP/IP协议的路通信的基本作单元。可以将Socket(套接字)看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。Socket(套接字)存在于通信域中,通信域是为了处理一般的线程通过Socket(套接字)通信而引进的一种抽象概念。Socket(套接字)通常和同一个域中的Socket(套接字)交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Internet协议簇来进行通信。
Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个Socket(套接字)都有其类型和一个与之相连进程。通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket(套接字)中,该 Socket(套接字)通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket(套接字)中,使对方能够接收到这段信息。 Socket(套接字)是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。
二、Socket(套接字)表达方式:
Socket(套接字)=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接地被通信两端的两个端点(即两个套接字)所确定。
例如: 如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)。
三、Socket(套接字)的主要类型:
1.流套接字(SOCK_STREAM)
流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无错、无重复送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Tranission Control Protocol)协议。
2.数据报套接字(SOCK_DGRAM)
数据报套接字提供一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP( User DatagramProtocol)协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。
3.原始套接字(SOCK_RAW)
原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据必须使用原始套接。
要通过互联网进行通信,至少需要一对套接字,其中一个运行于客户端,我们称之为 Socket,另一个运行于端,我们称之为 Socket。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:
客户端请求
连接确认
1.
所谓,是指端套接字并不具体的客户端套接字,而是处于等待连接的状态,实时网络状态。
2.客户端请求
所调客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是端的套接字。为此,客户端的套接字必须首先描述它要连接的的套接字,指出端套接字的地址和端口号,然后就向端接字提出连接请求。
3.连接确认
所谓连接确认,是指当端套接字到或者说接收到客户端套接字的连接请求,就会响应客户端套接字的请求,建立一个新的线程,并把端套接字的描述发送给客户端。一旦客户端确认了此描述,连接就建立好了。而端套接字继续处于状态,接收其他客户端套接字的连接请求。
根据套接字的不同类型,可以将套接字调用分为面向连接服务和无连接服务。
面向连接服务的主要特点如下:
(1)数据传输过程必须经过建立连接、维护连接和释放连接3个阶段;
(2)在传输过程中,各分组不需要携带目的主机的地址;
(3)可靠性好,但由于协议复杂,通信效率不高。
面向无连接服务的主要特点如下:
(1)不需要连接的各个阶段;
(2)每个分组都携带完整的目的主机地址,在系统中传送;
(3)由于没有顺序控制,所以接收方的分组可能出现乱序、重复和丢失现象;
(4)通信效率高,但可靠性不能确保。
用Socket进行同步通讯编程的详细步骤是怎样的?
【】:1、在应用程序和远程设备中使用协议和网络地址初始化套接字
2、在应用程序中通过指定端口和地址建立
3、远程设备发出连接请求
4、应用程序接受连接产生通信scoket
5、应用程序和远程设备开始通讯(在通讯中应用程序将挂起直到通讯结束)
6、通讯结束,关闭应用程序和远程设备的Socket回收资源
linux C语言编程,socket实现的即使通讯系统
//服务端server.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVPORT 6000 /端口号 /
#define BACKLOG 10 / 同时连接请求数 /
#define MAXDATASIZE 100
main()
{char buf[MAXDATASIZE];
int sockfd,client_fd; /sock_fd:socket;client_fd:数据传输socket /
struct sockaddr_in my_addr; / 本机地址信息 /
struct sockaddr_in remote_addr; / 客户端地址信息 /
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{perror("socket创建出错!");
exit(1);
}my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd, (struct sockaddr )&my_addr, sizeof(struct sockaddr)) == -1)
{perror("bind出错!");
exit(1);
}if (listen(sockfd, BACKLOG) == -1)
{perror("listen出错!");
exit(1);
}while(1)
{sin_size = sizeof(struct sockaddr_in);
if ((client_fd = accept(sockfd, (struct sockaddr )&remote_addr, &sin_size)) == -1)
{perror("accept出错");
continue;
}printf("received a connection from %sn", inet_ntoa(remote_addr.sin_addr));
if (!fork())
{ / 子进程代码段 /
if ((recvbytes=recv(client_fd, buf, MAXDATASIZE, 0)) ==-1)
{perror("recv出错!");
close(client_fd);
exit(0);
}buf[recvbytes] = '0';
printf("from client Received: %s",buf);
if (send(client_fd, "thanks!n", 8, 0) == -1)
perror("send出错!");
close(client_fd);
exit(0);
}close(client_fd);
}}
//客户端client.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVPORT 6000
#define MAXDATASIZE 100
main(int argc, char argv[])
{int sockfd, recvbytes;
char buf[MAXDATASIZE];
struct hostent host;
struct sockaddr_in serv_addr;
if (argc < 2)
{fprintf(stderr,"Please enter the server's hostname!n");
exit(1);
}if((host=gostbyname(argv[1]))==NULL)
{herror("gostbyname出错!");
exit(1);
}if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{perror("socket创建出错!");
exit(1);
}serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr = ((struct in_addr )host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if (connect(sockfd, (struct sockaddr )&serv_addr, sizeof(struct sockaddr)) == -1)
{perror("connect出错!");
exit(1);
}if (send(sockfd, "hello!n", 7, 0) == -1)
{perror("send出错!");
exit(1);
}if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1)
{perror("recv出错!");
exit(1);
}buf[recvbytes] = '0';
printf("Received: %s",buf);
close(sockfd);
}
//服务端server.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVPORT 6000 /端口号 /
#define BACKLOG 10 / 同时连接请求数 /
#define MAXDATASIZE 100
main()
{char buf[MAXDATASIZE];
int sockfd,client_fd; /sock_fd:socket;client_fd:数据传输socket /
struct sockaddr_in my_addr; / 本机地址信息 /
struct sockaddr_in remote_addr; / 客户端地址信息 /
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{perror("socket创建出错!");
exit(1);
}my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd, (struct sockaddr )&my_addr, sizeof(struct sockaddr)) == -1)
{perror("bind出错!");
exit(1);
}if (listen(sockfd, BACKLOG) == -1)
{perror("listen出错!");
exit(1);
}while(1)
{sin_size = sizeof(struct sockaddr_in);
if ((client_fd = accept(sockfd, (struct sockaddr )&remote_addr, &sin_size)) == -1)
{perror("accept出错");
continue;
}printf("received a connection from %sn", inet_ntoa(remote_addr.sin_addr));
if (!fork())
{ / 子进程代码段 /
if ((recvbytes=recv(client_fd, buf, MAXDATASIZE, 0)) ==-1)
{perror("recv出错!");
close(client_fd);
exit(0);
}buf[recvbytes] = '0';
printf("from client Received: %s",buf);
if (send(client_fd, "thanks!n", 8, 0) == -1)
perror("send出错!");
close(client_fd);
exit(0);
}close(client_fd);
}}
//客户端client.c
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVPORT 6000
#define MAXDATASIZE 100
main(int argc, char argv[])
{int sockfd, recvbytes;
char buf[MAXDATASIZE];
struct hostent host;
struct sockaddr_in serv_addr;
if (argc < 2)
{fprintf(stderr,"Please enter the server's hostname!n");
exit(1);
}if((host=gostbyname(argv[1]))==NULL)
{herror("gostbyname出错!");
exit(1);
}if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{perror("socket创建出错!");
exit(1);
}serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr = ((struct in_addr )host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if (connect(sockfd, (struct sockaddr )&serv_addr, sizeof(struct sockaddr)) == -1)
{perror("connect出错!");
exit(1);
}if (send(sockfd, "hello!n", 7, 0) == -1)
{perror("send出错!");
exit(1);
}if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1)
{perror("recv出错!");
exit(1);
}buf[recvbytes] = '0';
printf("Received: %s",buf);
close(sockfd);
}
通过Socket实现网络编程的主要过程是什么?
socket——套接字~网络间的进程是靠这个套接字进行通信~
在编程时会用到的函数:socket()
bind()
listen()
read() / write()
close()
这是一套完整的流程~具体各函数的定义以及用法可以再百度百科里找到~
先去看书吧孩子,《unix网络编程(卷1:套接字)(卷2:进程间通信)》
实验四,web套接字编程怎么做
1.TCP流式套接字的编程步骤
在使用之前须链接库函数:工程->设置->Link->输入ws2_32.lib,OK!
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);//创建套接字(socket)。
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//转换Unsigned short为网络字节序的格式
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
客户端代码如下:
#include
#include
void main()
{WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );加载套接字库
if ( err != 0 ) {
return;
}if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup()( );
return;
}SOCKET sock=socket(AF_INET,SOCK_STREAM,0);创建套接字(socket)。
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
connect(sock,(SOCKADDR)&addrSrv,sizeof(SOCKADDR));向发出连接请求(connect)。
char recvBuf[100];和端进行通信(send/recv)。
recv(sock,recvBuf,100,0);
printf("%sn",recvBuf);
send(sock,"This is lisi",strlen("This is lisi")+1,0);
closesocket(sock);关闭套接字。
WSACleanup()();//必须调用这个函数清除参数
}
如何编写一个利用Socket通信的程序?
设计思路
本例包括一个端程序和一个客户端程序。客户端程序可以放到多个计算机上运行,同时与端进行连接通信。
本例的重点,一是演示客户端与端如何通信;二是当有多个客户端同时连接到端时,端如何识别每个客户端,并对请求给出相应的回复。为了保证一个客户端断开连接时不影响其它客户端与端的通信,同时保证端能够正确回复客户端的请求,在本例中声明了一个记录类型:
type
client_record=record
CHandle: integer; //客户端套接字句柄
CSocket:TCustomWinSocket; //客户端套接字
CName:string; //客户端计算机名称
CAddress:string; //客户端计算机IP地址
CUsed: boolean; //客户端联机标志
end;
利用这个记录类型数据保存客户端的信息,同时保存当前客户端的连接状态。其中,CHandle保存客户端套接字句柄,以便准确每个与端保持连接的客户端;Csocket保存客户端套接字,通过它可以对客户端进行回复。Cused记录当前客户端是否与端保持连接。
下面对组件Socket和Socket的属性设置简单说明。
Socket的属性:
· Port,是通信的端口,必须设置。在本例中设置为1025;
· Typt,端读写信息类型,设置为stNonBlocking表示异步读写信息,本例中采用这种方式。
· ThreadCacheSize,客户端的连接数,就是端多允许多少客户端同时连接。本例采用默认值10。
其它属性采用默认设置即可。
Socket的属性:
· Port,是通信的端口,必须与端的设置相同。在本例中设置为1025;
· Type,客户端读写信息类型,应该与端的设置相同,为stNonBlocking表示异步读写信息。
· Host,客户端要连接的的IP地址。必须设置,当然也可以在代码中动态设置。
其它属性采用默认设置即可。
程序源代码:
· 端源码(uMain.pas):
unit uMain;
intece
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, ToolWin, ComCtrls, ExtCtrls, StdCtrls, Buttons;
const
CMax=10; //客户端连接数
type
client_record=record
CHandle: integer; //客户端套接字句柄
CSocket:TCustomWinSocket; //客户端套接字
CName:string; //客户端计算机名称
CAddress:string; //客户端计算机IP地址
CUsed: boolean; //客户端联机标志
end;
type
TfrmMain = class(TForm)
Socket: TSocket;
ControlBar1: TControlBar;
ToolBar1: TToolBar;
tbConnect: TToolButton;
tbClose: TToolButton;
tbDisconnected: TToolButton;
Edit1: TEdit;
Memo1: TMemo;
StatusBar: TStatusBar;
procedure tbConnectClick(Sender: TObject);
procedure tbDisconnectedClick(Sender: TObject);
procedure SocketRead(Sender: TObject;Socket: TCustomWinSocket);
procedure SocketListen(Sender: TObject;Socket: TCustomWinSocket);
procedure SocketConnect(Sender: TObject;Socket: TCustomWinSocket);
procedure SocketDisconnect(Sender: TObject;Socket: TCustomWinSocket);
procedure tbCloseClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure SocketGetSocket(Sender: TObject; Socket: Integer;
var Socket: TWinSocket);
procedure SocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
private
{Private declarations
}public
{Public declarations
}session: array[0..CMax] of client_record; //客户端连接数组
Sessions: integer; //客户端连接数
end;
var
frmMain: TfrmMain;
implementation
{$R .DFM}
//打开套接字连接,并使套接字进入状态
procedure TfrmMain.tbConnectClick(Sender: TObject);
begin
Socket.Open ;
end;
//关闭套接字连接,不再客户端的请求
procedure TfrmMain.tbDisconnectedClick(Sender: TObject);
begin
Socket.Close;
StatusBar.Panels[0].Text :='套接字连接已经关闭,无法接受客户端的连接请求.';
end;
//从客户端读取信息
procedure TfrmMain.SocketRead(Sender: TObject;Socket: TCustomWinSocket);
var
i:integer;
begin
//将从客户端读取的信息添加到Memo1中
Memo1.Lines.Add(Socket.ReceiveText);
for i:=0 to sessions do
begin
//取得匹配的客户端
if session[i].CHandle = Socket.SocketHandle then
begin
session[i].CSocket.SendText('回复客户端'+session[i].CAddress+' ==> '+Edit1.Text);
end;
end;
end;
//端套接字进入状态,以便客户端的连接
procedure TfrmMain.SocketListen(Sender: TObject;Socket: TCustomWinSocket);
begin
StatusBar.Panels[0].Text :='等待客户端连接...';
end;
//当客户端连接到端以后
procedure TfrmMain.SocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i,j:integer;
begin
j:=-1;
for i:=0 to sessions do
begin
//在原有的客户端连接数组中有中断的客户端连接
if not session[i].CUsed then
begin
session[i].CHandle := Socket.SocketHandle ;//客户端套接字句柄
session[i].CSocket := Socket; //客户端套接字
session[i].CName := Socket.RemoteHost ; //客户端计算机名称
session[i].CAddress := Socket.RemoteAddress ;//客户端计算机IP
session[i].CUsed := True; //连接数组当前位置已经占用
Break;
end;
j:=i;
end;
if j=sessions then
begin
inc(sessions);
session[j].CHandle := Socket.SocketHandle ;
session[j].CSocket := Socket;
session[j].CName := Socket.RemoteHost ;
session[j].CAddress := Socket.RemoteAddress ;
session[j].CUsed := True;
end;
StatusBar.Panels[0].Text := '客户端 '+Socket.RemoteHost + ' 已经连接';
end;
//当客户端断开连接时
procedure TfrmMain.SocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i:=0 to sessions do
begin
if session[i].CHandle =Socket.SocketHandle then
begin
session[i].CHandle :=0;
session[i].CUsed := False;
Break;
end;
end;
StatusBar.Panels[0].Text :='客户端 '+Socket.RemoteHost + ' 已经断开';
end;
//关闭窗口
procedure TfrmMain.tbCloseClick(Sender: TObject);
begin
Close;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
sessions := 0;
end;
procedure TfrmMain.FormClose(Sender: TObject;var Action: TCloseAction);
begin
Socket.Close ;
end;
//当客户端正在与端连接时
procedure TfrmMain.SocketGetSocket(Sender: TObject;
Socket: Integer; var Socket: TWinSocket);
begin
StatusBar.Panels[0].Text :='客户端正在连接...';
end;
//客户端发生错误
procedure TfrmMain.SocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
StatusBar.Panels[0].Text :='客户端'+Socket.RemoteHost +'发生错误!';
ErrorCode := 0;
end;
end.
液晶面板类型 全球面板价格走势图
液晶面板的类型有哪些? 目前市场上最常见的液晶面板技术有5种,分别是CPA、MVA/S-MVA、PVA/SPVA、IPS/S-IPS和AS-IPS。这几种技术又分两大阵营,CPA、MVA/S、MVA、PVA/SPVA同属于VA阵营,为垂直配向技术。其···
平板电脑全新超薄12寸(12寸平板电脑尺寸对照
小怡今天给分享平板电脑全新超薄12寸的知识,其中也会对12寸平板电脑尺寸对照图进行解释,希望能解决你的问题,请看下面的文章阅读吧! 平板电脑全新超薄12寸(12寸平板电脑尺寸对照图) 平板···
斗战神猴子攻略 斗战神猴子刷图2021
小乐今天给分享斗战神猴子攻略的知识,其中也会对斗战神猴子刷图2021进行解释,希望能解决你的问题,请看下面的文章阅读吧! 斗战神猴子攻略 斗战神猴子刷图2021 斗战神猴子攻略 斗战神猴子···