上面所写都是利用控件(TClientSocket/TServerSocket或CAsyncSocket)实现的,它们都对
Socket API做了封装,你看不到底层的东西,所以觉得很神秘。其实Socket也就是几个API而已,
是比较简单的。
我举个TCP的例子(Console程序):
TCP Client:
-------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <winsock2.h>
#include <memory.h>
#define SERVER_PORT 5432
#define MAX_LINE 256
void
main(int argc,char * argv[])
{
struct sockaddr_in sin;
struct hostent *hp;
char *host;
char buf[MAX_LINE];
int s;
int len;
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (argc==2){
host = argv[1];
}
else {
fprintf(stderr,"usage:Client host/n");
exit(1);
}
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
exit(1);
}
/*translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk unknow host: %s/n",host);
exit(1);
}
/*build address data structure */
memset((char *)&sin, 0,sizeof(sin));
sin.sin_family = AF_INET;
memcpy((char *)&sin.sin_addr,hp->h_addr_list[0], hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/*active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
perror("simplex-talk:socket");
exit(1);
}
if (connect(s, (struct sockaddr *)&sin, sizeof(sin))!=0){
perror("simplex-talk:connect");
closesocket(s);
exit(1);
}
printf("connection established!/n");
/*main loop:get and send lines of text */
while (fgets(buf, sizeof(buf), stdin)) {
buf[MAX_LINE-1] = '/0';
len = strlen(buf) +1;
if ((send(s,buf,len,0))<0) {
printf("Socket error!/n");
closesocket(s);
exit(1);
}
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TCP Server:
--------------------
#include <stdio.h>
#include <sys/types.h>
#include <winsock2.h>
#include <memory.h>
#define SERVER_PORT 5432
#define MAX_PENDING 5
#define MAX_LINE 256
void
main()
{
struct sockaddr_in sin;
struct sockaddr_in sout;
char buf[MAX_LINE];
int len;
int lens;
SOCKET s,new_s;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
exit(1);
}
/*build address data structure */
memset((char *)&sin,0,sizeof(struct sockaddr));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/*setup passive open*/
if ((s=socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET ){
perror("simplex-talk:socket");
exit(1);
}
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) != 0){
perror("simplex-talk:bind");
exit(1);
}
if ((listen(s,MAX_PENDING))!=0){
perror("simplex-talk:listen");
exit(1);
}
/*wait for connection, then receive and print text */
while(1){
memcpy((char *)&sout,(char *)&sin,sizeof(struct sockaddr_in));
lens=sizeof(sout);
printf("waiting.../n");
if ((new_s =accept(s,(struct sockaddr *)&sout,&lens)) == INVALID_SOCKET) {
perror("simplex-talk:accept");
exit(1);
}
printf("connection established!/n");
while((len=recv(new_s,buf,sizeof(buf),0))>0){
fputs(buf,stdout);
}
printf("socket closed!/n");
closesocket(new_s);
}
}
============================================
我再举个Delphi的UDP的例子(图形界面程序):
unit udp;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, winsock,
StdCtrls;
const
WM_SOCK = WM_USER + 1; //自定义windows消息
UDPPORT = 646; //设定UDP端口号
type
Tfrmmain = class(TForm)
Button1: TButton;
Edit1: TEdit;
Memo1: TMemo;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
s: TSocket;
addr: TSockAddr;
FSockAddrIn : TSockAddrIn;
//利用消息实时获知UDP消息
procedure ReadData(var Message: TMessage);
message WM_SOCK;
public
{ Public declarations }
procedure SendData(Content: String);
end;
var
frmmain: Tfrmmain;
implementation
{$R *.DFM}
procedure Tfrmmain.FormCreate(Sender: TObject);
var
TempWSAData: TWSAData;
//optval: integer;
begin
// 初始化SOCKET
if WSAStartup($101, TempWSAData)=1 then
showmessage('StartUp Error!');
s := Socket(AF_INET, SOCK_DGRAM, 0);
if (s = INVALID_SOCKET) then //Socket创建失败
begin
showmessage(inttostr(WSAGetLastError())+' Socket创建失败');
CloseSocket(s);
// exit;
end;
//发送方SockAddr绑定
addr.sin_family := AF_INET;
addr.sin_addr.S_addr := INADDR_ANY;
addr.sin_port := htons(UDPPORT);
if Bind(s, addr, sizeof(addr)) <> 0 then
begin
showmessage('bind fail');
end;
{optval:= 1;
if setsockopt(s,SOL_SOCKET,SO_BROADCAST,pchar(@optval),sizeof(optval)) = SOCKET_ERROR then
begin
showmessage('无法进行UDP广播');
end;}
WSAAsyncSelect(s, frmmain.Handle , WM_SOCK, FD_READ);
//接收端SockAddrIn设定
FSockAddrIn.SIn_Family := AF_INET;
FSockAddrIn.SIn_Port := htons(UDPPORT);
label3.Caption := '端口:'+inttostr(UDPPORT);
end;
procedure Tfrmmain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(s);
end;
procedure Tfrmmain.ReadData(var Message: TMessage);
var
buffer: Array [1..4096] of char;
len: integer;
flen: integer;
Event: word;
value: string;
begin
flen:=sizeof(FSockAddrIn);
FSockAddrIn.SIn_Port := htons(UDPPORT);
Event := WSAGetSelectEvent(Message.LParam);
if Event = FD_READ then
begin
len := recvfrom(s, buffer, sizeof(buffer), 0, FSockAddrIn, flen);
value := copy(buffer, 1, len);
Memo1.Lines.add(value)
end;
end;
procedure Tfrmmain.SendData(Content: String);
var
value{,hostname}: string;
len: integer;
begin
FSockAddrIn.SIn_Addr.S_addr := inet_addr(pchar(Edit1.text)); //INADDR_BROADCAST; //INADDR_BROADCAST = -1 ?
value := Content;
len := sendto(s, value[1], Length(value), 0, FSockAddrIn, sizeof(FSockAddrIn));
if (WSAGetLastError() <> WSAEWOULDBLOCK) and (WSAGetLastError() <> 0) then
showmessage(inttostr(WSAGetLastError()));
if len = SOCKET_ERROR then
showmessage('send fail');
if len <> Length(value) then
showmessage('Not Send all');
end;
procedure Tfrmmain.Button1Click(Sender: TObject);
begin
senddata(Edit2.text);
end;
end.
======================================
不要被控件或类的封装所迷惑,Socket不过如此。