導航:首頁 > 編程語言 > delphi下的sock編程

delphi下的sock編程

發布時間:2022-05-04 17:48:52

A. DELPHI上簡單高效的SOCKET控制項怎麼選擇

主要用非同步通訊方式
直接api,winsock

參考之:


SOCKET控制項與直接使用API相比

Windows自帶的Tracert是向遠程主機發送ICMP包進行追蹤,但是目前很多主機關閉了ICMP答復,這個工具不太好使了~~~~~原理咱知道,正規的Trace不就是發送TTL依次遞增的UDP包嗎?什麼網關和路由敢隨意丟棄我們的UDP包而不通知我們?ICMP包你可以不理,但是UDP包~~~~~不怕黑你???

unit YRecords;

interface

uses
Windows;

const
PACKET_SIZE = 32;
MAX_PACKET_SIZE = 512;
TRACE_PORT = 34567;
LOCAL_PORT = 5555;

type
s32 = Integer;
u32 = DWORD;
u8 = Byte;
u16 = word; PU16 = ^U16;

//
//IP Packet Header
//
PIPHeader = ^YIPHeader;
YIPHeader = record
u8verlen : u8;//4bits ver, 4bits len, len*4=true length
u8tos : u8;//type of service, 3bits 優先權(現在已經被忽略), 4bits TOS, 最多隻能有1bit為1
u16totallen : u16;//整個IP數據報的長度,以位元組為單位。
u16id : u16;//標識主機發送的每一份數據報。
u16offset : u16;//3bits 標志,13bits片偏移
u8ttl : u8;//生存時間欄位設置了數據報可以經過的最多路由器數。
u8protol : u8;//協議類型,6表示傳輸層是TCP協議。
u16checksum : u16;//首部檢驗和。
u32srcaddr : u32;//源IP地址,不是『xxx.xxx.xxx.xxx』的形勢哦
u32destaddr : u32;//目的IP地址,同上
end;

//
//ICMP Packet Header
//
PICMPHeader = ^YICMPHeader;
YICMPHeader = record
u8type : u8;
u8code : u8;
u16chksum : u16;
u16id : u16;
u16seq : u16;
end;

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, YRecords, winsock2;

type
TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
Button1: TButton;
procere FormCreate(Sender: TObject);
procere FormClose(Sender: TObject; var Action: TCloseAction);
procere Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function DecodeIcmpReply( pbuf: PChar; var seq: s32 ): string;
var
pIpHdr : PChar;
pIcmphdr : PICMPHeader;
sip : string;
ttl : integer;
begin
pIpHdr := pbuf;
sip := inet_ntoa( TInAddr( PIPHeader(pIpHdr)^.u32srcaddr ) );
ttl := PIPHeader(pIpHdr)^.u8ttl;

Inc( pIpHdr, (PIPHeader(pIpHdr)^.u8verlen and $0F) * 4 );
pIcmpHdr := PICMPHeader(pIpHdr);

result := ;
if pIcmpHdr^.u8type = 3 then //目的不可達信息,Trace完成
seq := 0;
if pIcmpHdr^.u8type = 11 then //超時信息,正在Trace
result := Format( %4d%32s%8d, [seq, sip, ttl] );
end;

procere ErrMsg( msg: string );
begin
MessageBox( 0, PChar(msg), Ping Program Error, MB_ICONERROR );
end;

procere TForm1.FormCreate(Sender: TObject);
var
wsa : TWSAData;
begin
if WSAStartup( $0202, wsa ) <> 0 then
ErrMsg( Windows socket is not responed. );
ListBox1.Font.Name := Courier New;
ListBox1.Font.Size := 9;
end;

procere TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if WSACleanup <> 0 then
ErrMsg( Windows socket can not be closed. );
end;

procere TForm1.Button1Click(Sender: TObject);
const
SIO_RCVALL = IOC_IN or IOC_VENDOR or 1;
var
rawsock : TSocket;
pRecvBuf : PChar;
FromAdr : TSockAddr;
FromLen : s32;
fd_read : TFDSet;
timev : TTimeVal;
sReply : string;
udpsock : TSocket;
ret : s32;
DestAdr : TSockAddr;
pSendBuf : PChar;
ttl, opt : s32;
pHost : PHostEnt;
begin
//創建一個RAWSOCK接收回應ICMP包
rawsock := socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );

FromAdr.sin_family := AF_INET;
FromAdr.sin_port := htons(0);
FromAdr.sin_addr.S_addr := inet_addr(192.168.1.12); //換成你的IP

//如果不bind就無法接收包了~~~因為下面還要創建一個UDPSOCK
bind( rawsock, @FromAdr, SizeOf(FromAdr) );

Opt := 1;
WSAIoctl( rawsock, SIO_RCVALL, @Opt, SizeOf(Opt), nil, 0, @ret, nil, nil );

//接收ICMP回應包的緩沖區
pRecvBuf := AllocMem( MAX_PACKET_SIZE );

//創建一個UDPSOCK發送探測包
udpsock := socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );

//要發送的UDP數據
pSendBuf := AllocMem( PACKET_SIZE );
FillChar( pSendBuf^, PACKET_SIZE, C );

FillChar( DestAdr, sizeof(DestAdr), 0 );
DestAdr.sin_family := AF_INET;
DestAdr.sin_port := htons( TRACE_PORT );
DestAdr.sin_addr.S_addr := inet_addr( PChar(Edit1.Text) );

//如果edit1.text不是IP地址,則嘗試解析域名
if DestAdr.sin_addr.S_addr = INADDR_NONE then
begin
pHost := gethostbyname( PChar(Edit1.Text) );
if pHost <> nil then
begin
move( pHost^.h_addr^^, DestAdr.sin_addr, pHost^.h_length );
DestAdr.sin_family := pHost^.h_addrtype;
DestAdr.sin_port := htons( TRACE_PORT );
ListBox1.Items.Add( Edit1.Text +IP地址->+ inet_ntoa(DestAdr.sin_addr) );
end else
begin
ListBox1.Items.Add( 解析域名: + Edit1.Text + 出錯。 );
closesocket( rawsock );
closesocket(udpsock);
FreeMem( pSendBuf );
FreeMem( pRecvBuf );
exit;
end;
end;

ListBox1.Items.Add( Trace route + Edit1.Text + ...... );
Listbox1.Update;

//開始Trace!!!
ttl := 1;
while True do
begin
//設置TTL,使我們發送的UDP包的TTL依次累加
setsockopt( udpsock, IPPROTO_IP, IP_TTL, @ttl, sizeof(ttl) );
//發送UDP包到HOST
sendto( udpsock, pSendBuf^, PACKET_SIZE, 0, DestAdr, sizeof(DestAdr) );

FD_ZERO( fd_read );
FD_SET( rawsock, fd_read );
timev.tv_sec := 5;
timev.tv_usec := 0;

if select( 0, @fd_read, nil, nil, @timev ) < 1 then
break;

if FD_ISSET( rawsock, fd_read ) then
begin
FillChar( pRecvBuf^, MAX_PACKET_SIZE, 0 );
FillChar( FromAdr, sizeof(FromAdr), 0 );
FromAdr.sin_family := AF_INET;
FromLen := sizeof( FromAdr );
recvfrom( rawsock, pRecvBuf^, MAX_PACKET_SIZE, 0, FromAdr, FromLen );

sReply := DecodeIcmpReply( pRecvBuf, ttl );
if sReply <> then
begin
ListBox1.ItemIndex := ListBox1.Items.Add( sReply );
Listbox1.Update;
end;
if ttl = 0 then //如果收到目標主機的相應包,DecodeIcmpReply會把ttl==0
break;
end;

Inc( ttl );
Sleep( 110 );
end; //while not bStop do

ListBox1.Items.Add( 追蹤路由完成。 );
ListBox1.Items.Add( );

closesocket( rawsock );
closesocket(udpsock);
FreeMem( pSendBuf );
FreeMem( pRecvBuf );
end;

end.


------解決方案--------------------
如果壓力較大
感覺標準的不如indy
indy不如api
------解決方案--------------------
upup...
------解決方案--------------------
用INDY好點,API有點復雜
------解決方案--------------------
ICS 用了都說好!
------解決方案--------------------
1000以下的連接用INDY不錯,1000以上考慮自己封裝完成埠。
------解決方案--------------------
所有VCL用FastMM檢測都有哪個內存泄漏的提示,如果只有一個可以忽略,樓主看看源代碼就知道了。
------解決方案--------------------
簡單高效就是serversocket和clientsocket

B. delphi怎樣用socket發送,接受record類型的數據

網路應用分為客戶端和服務端兩部分,而Socket類是負責處理客戶端通信的java類。通過這個類可以連接到指定IP或域名的伺服器上,並且可以和伺服器互相發送和接受數據。在本文及後面的數篇文章中將詳細討論Socket類的使用,內容包括Socket類基礎、各式各樣的連接方式、get和set方法、連接過程中的超時以及關閉網路連接等。

在本文中,我們將討論使用Socket類的基本步驟和方法。一般網路客戶端程序在連接服務程序時要進行以下三步操作。

1.連接伺服器

2.發送和接收數據

3.關閉網路連接

一、連接伺服器

在客戶端可以通過兩種方式來連接伺服器,一種是通過IP的方式來連接伺服器,而另外一種是通過域名方式來連接伺服器。

其實這兩種方式從本質上來看是一種方式。在底層客戶端都是通過IP來連接伺服器的,但這兩種方式有一定的差異,如果通過IP方式來連接服務端程序,客戶端只簡單地根據IP進行連接,如果通過域名來連接伺服器,客戶端必須通過DNS將域名解析成IP,然後再根據這個IP來進行連接。

在很多程序設計語言或開發工具中(如C/C++、Delphi)使用域名方式連接伺服器時必須自己先將域名解析成IP,然後再通過IP進行連接,而在Java中已經將域名解析功能包含在了Socket類中,因此,我們只需象使用IP一樣使用域名即可。

通過Socket類連接伺服器程序最常用的方法就是通過Socket類的構造函數將IP或域名以及埠號作為參數傳入Socket類中。Socket類的構造函數有很多重載形式,在這一節只討論其中最常用的一種形式:public Socket(String host, int port)。從這個構造函數的定義來看,只需要將IP或域名以及埠號直接傳入構造函數即可。下面的代碼是一個連接服務端程序的例子程序:

package mysocket;

import java.net.*;

public class MyConnection

{

public static void main(String[] args)

{

try

{

if (args.length > 0)

{

Socket socket = new Socket(args[0], 80);

System.out.println(args[0] + "已連接成功!");

}

else

System.out.println("請指定IP或域名!");

}

catch (Exception e)

{

System.err.println("錯誤信息:" + e.getMessage());

}

}

}

在上面的中,通過命令行參數將IP或域名傳入程序,然後通過Socket socket = new Socket(args[0], 80)連接通過命令行參數所指定的IP或域名的80埠。由於Socket類的構造函數在定義時使用了throws,因此,在調用Socket類的構造函數時,必須使用try…catch語句來捕捉錯誤,或者對main函數使用throws語句來拋出錯誤。

測試正確的IP

java mysocket.MyConnection 127.0.0.1

輸出結果:127.0.0.1已經連接成功!

測試錯誤的IP

java mysocket.MyConnection 10.10.10.10

輸出結果:錯誤信息:Connection timed out: connect

註:10.10.10.10是一個並不存在的IP,如果這個IP在你的網路中存在,請使用其它的不存在的IP。

測試正確的域名

java mysocket.MyConnection www.ptpress.com.cn

輸出結果:www.ptpress.com.cn已經連接成功!

測試錯誤的域名

java mysocket.MyConnection www.ptpress1.com.cn

輸出結果:錯誤信息:www.ptpress1.com.cn

使用Socket類連接伺服器可以判斷一台主機有哪些埠被打開。下面的代碼是一個掃描本機有哪些埠被打開的程序。

C. 在delphi中如何用clientsocket進行實時發送。。即在資料庫讀取到數據就立即發送出去。。

如果是資料庫中直接可以發送出去的話, 就用觸發器。

如果是自己開發程序, 需要程序來發送出去的話, 就在程序中用Timer控制項,
在OnTimer事件中讀取資料庫中A表數據, A表需要用觸發器來寫入數據, 可以把需要發送出去的數據在觸發器中寫入到A表, 那麼在程序每次讀取到A表數據後就通過程序來發送, 這個不難吧?

我不知道你要發送的是具體數據呢, 還是數據集, 數據集就相對比較麻煩點了, 我也沒研究過這個, 不知道是否可以用Stream來操作。

D. 誰能給我一個用Delphi寫SOCKS5代理伺服器的常式

所謂代理伺服器 就是代理網路用戶去取得網路信息。形象的說,它是網路信息的中轉站.

E. Delphi下的socket(如TServerSocket)為什麼沒有超時屬性,

waitfor函數來確定一個socket的超時設置,有msgwaitformultipleobjects,
msgwaitforsingleobject,
或用winsock.select函數也可。如果是block方式一般用線程方式來操作,使用waitfor來確定是否超時,或有數據來。。。通過setsockopt可以設置socket
recv
buffer
sizesetsockopt(clientsocket1.socket.sockethandle,
SOL_SOCKET,SO_recv{這參數叫接收buffer,查一下help},
pchar(&BufSize),
SizeOf(BufSize));
具體看一下scktcomp.pas源碼
查看原帖>>

F. delphi socket編程 幫忙看下

這樣寫其實是有點問題的,立即連接馬上就發送,個人認為在將來網路上應用的話肯定會丟失發送內容,不知具體如何,到時你試過如果真的完全沒有問題麻煩告訴我一聲。

至於你說發送出去別人收到的都不對,估計是因為bs:array of byte;的問題!!

如果你是這樣定義的話bs:array[0..3] of byte; 且不要下面的setlength那句,應該別人收到的是對的

G. 如何用delphi socket 傳遞自定義對象

參考代碼:
(1) delphi客戶端發送:

csConnect()中

tmpstr := ipcode + '|setclient|' + ip + '|' + mac + '|' + #13#10;
Socket.SendText(tmpstr);

(2)Java服務接受:

public ServerThread2(Socket s) { // serverThread的構造器
this.request = s;
// 接收receiveServer傳來的套接字
try { // 初始化輸入、輸出流
response = new DataOutputStream(request.getOutputStream());
input = new DataInputStream(request.getInputStream());
} catch (IOException e) {
GlobaTx.LogLn(e.getMessage());
}
}

@Override
public void run() { // 線程的執行方法
String str = "";
//StringBuilder sb=new StringBuilder();

str = input.readLine();

//下邊詳細處理

}

(3)java服務端返回:

/**
* 發送報文到客戶端
* @param response
* @param pg
* @return
*/
public static boolean writePg(DataOutputStream response, DataPg pg) {
try {
String tmp=pg.getReturnStr()+"*";
System.out.println("sender:"+tmp);
response.writeBytes(tmp);//(s)writeUTF
response.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
}
}

(4)delphi客戶端接收:

csRead()中

res := Socket.ReceiveText;
tmpstr := res[length(res)];
if tmpstr <> '*' then //約定的結束字元*,防止傳送不完整串
begin
pgcs := pgcs + res;
Exit;
end;
res := pgcs + res;
pgcs := '';

--------------------------------------------------------------------------------------------------------------------

大文件傳送:

(1)delphi發送

procere TForm1.csfileConnect(Sender: TObject; Socket: TCustomWinSocket);
var
Buf: array[1..MAX_BUF + 1] of char;
bytes, iLength, MySendLength: Integer;
res, tmpstr, Msg: string;
bufSend: pointer;
picname: string; //保存的照片名稱
ipcode: string; //機器編號
timestr: string; //時間
lt: TSYSTEMTIME;
begin
res := pg;
ipcode := tools.findsegment(res, 1, '|');
GetLocalTime(lt);

picname := ipcode + '-' + inttostr(lt.wYear) +
inttostr(lt.wMonth) + inttostr(lt.wDay) + inttostr(lt.wHour)
+ inttostr(lt.wMinute) + inttostr(lt.wSecond) + '.bmp';
tools.CaptureScreen(picname);
while tools.IsFileInUse(picname) do
begin
end;
fsSend := TFileStream.Create(picname, fmOpenRead);
Socket.SendText(ipcode + '|uppic|' + picname + '|' + inttostr(fsSend.Size) + '|' + #13#10);
if fsSend.Size > 0 then
begin
while fsSend.Position < fsSend.Size do
begin
iLength := fsSend.Size;
// - fsSend.Position;
//將數據分段發送
// if iLength > MAX_BUF then
// iLength := MAX_BUF;
GetMem(bufSend, iLength);
try
//讀取文件流數據
fsSend.Read(bufSend^, iLength);
//發送長度為iLength的數據
Socket.SendBuf(bufSend^, iLength);
//進度條顯示
// Probar.Position := fsSend.Position;
finally
//釋放內存
FreeMem(bufSend, iLength);
end;
end;
//Socket.Close();
Timer1.Enabled := True;
end;
end;

(2)java接收

public static boolean fileWriteIn(File file, DataInputStream downStream,long length) {
FileOutputStream fileWrite = null;
try {
fileWrite = new FileOutputStream(file);

byte[] buffer = new byte[size];
int len = 0;
long n = 0;
System.out.print(" >開始接受數據,寫入文件 ");
while ((len = downStream.read(buffer, 0, size)) != -1) {
fileWrite.write(buffer, 0, len);
n += len;
System.out.print(".");
if ((n + size) > length) {
int lastLen = (int) (length - n);
n += lastLen;
len = downStream.read(buffer, 0, lastLen);
fileWrite.write(buffer, 0, len);
System.out.print("-");
break;
}
}

System.out.println(" >完成接受,長度為:" + n);

//接收完成==========================
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error: " + e.getMessage());
return false;
} finally {

try {
fileWrite.close();
} catch (IOException e) {

}
}
}

----------------------------------------------------------------------------

中文傳送:

msg:=UTF8Decode(HttpDecode(msg)) ;
// URLdecode(msg);
showmessage(Msg);

destr = URLEncoder.encode(body, "utf-8");
System.out.println("-URL-----------"+destr+"------------");

H. delphi中使用sock或tcp/udp

可以使用Delphi自帶的控制項TTcpClient。
使用步驟:設置好主機地址和埠;響應連接事件,在連接事件中記錄連接狀態;響應讀數據事件,顯示收到的數據;調用連接方法;連接後按伺服器要求的格式發送數據;完畢。

I. socket 編程問題~~~~~~~急~~~~~~~~~~Access violation at address

可能是系統連接數受限吧,你可以在程序中斷開某一個連接,給它騰位置

J. delphi中如何實現多線程socket通信時

我再說具體些,在delphi中實現收集socket通信時,應用TserverSocket類做辦事器端,個中該類的ServerType屬性有兩個選擇,分別決定辦事器端是為每個客戶request生成一個線程(選stThreadBlocking)照樣所有的客戶request都在一個線程中處理(選stNonBlocking),當我選擇stThreadBlocking用線程方法時,客戶端發送信息時,辦事器端不克不及激活OnClientRead事宜,而被選擇非線程方法時則可以實現。

閱讀全文

與delphi下的sock編程相關的資料

熱點內容
如何壓縮文件夾聯想電腦 瀏覽:583
程序員的學習之旅 瀏覽:440
apkdb反編譯 瀏覽:922
雪花演算法為什麼要二進制 瀏覽:825
在文檔中打開命令行工具 瀏覽:608
android圖標尺寸規范 瀏覽:369
python實用工具 瀏覽:208
流量計pdf 瀏覽:936
科東加密認證價格 瀏覽:532
dos命令讀文件 瀏覽:996
成為程序員需要什麼學歷 瀏覽:672
pdf農葯 瀏覽:228
canal加密 瀏覽:497
日本安卓系統和中國有什麼區別 瀏覽:137
linux命令行修改文件 瀏覽:838
從編譯和解釋的角度看 瀏覽:649
徐志摩pdf 瀏覽:651
夏天解壓球視頻 瀏覽:304
全封閉壓縮機qd91h 瀏覽:668
如何在我的世界免費開一個伺服器 瀏覽:329