什么是Socket
- 它是使用Unix文件描述符(fd)和其他程序通讯的方式。用于描述IP和端口
Internet套接字的两种类型
- 流格式(Stream Socket)SOCK_STREAM 。TCP可靠
- 数据包格式(datagram Socket) SOCK_DGRAM。UDP不可靠
客户端与服务器的交互
C#服务器代码
-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SimpleServer
{
class Program
{
static void Main(string[] args)
{
// 服务器IP地址
string ip = "127.0.0.1";
//服务器端口
int port = 8000;
try
{
//获得终端地址
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), port);
//创建socket
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将socket绑定到终端地址上
listener.Bind(ipe);
//开始监听,最大允许处理1000个连接
listener.Listen(1000);
Console.WriteLine("开始监听");
// 开始接受客户端请求,程序在这里会阻塞住
Socket mySocket = listener.Accept();
byte[] bs = new byte[1024];
int n = mySocket.Receive(bs);
// 将客户端发来的数据返回给客户端。
mySocket.Send(bs);
mySocket.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
C#客户端代码
-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SimpleClient
{
class Program
{
static void Main(string[] args)
{
// 服务器IP地址
string ip = "127.0.0.1";
//服务器端口
int port = 8000;
try
{
// 获得终端地址
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), port);
//创建socket
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//开始连接服务器,程序会在这里阻塞
client.Connect(ipe);
Console.WriteLine("连接到服务器");
string data = "hello world";
byte[] bs = UTF8Encoding.UTF8.GetBytes(data);
client.Send(bs);
//接受服务器传回的数据
byte[] rev = new byte[256];
client.Receive(rev);
Console.WriteLine(UTF8Encoding.UTF8.GetString(rev));
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
sockaddr和sockaddr_in的区别
- 都是用来处理网络通信的地址
- sockaddr把ip地址和端口混在一起。#include <sys/socket.h>定义
- sockaddr_in把ip和端口分开。 在 #include<netinet/in.h>或#include <arpa/inet.h>中定义
- 套接字 = IP + 端口
-
htons()[host to net short]
- htons()端口号由主机字节序转换为网络字节序的整数
- 主机字节序 = 小端字节序(现代PC多是小端) 网络字节序 = 大端字节序 。 并学会如何测试大小端
inet_addr()
- inet_addr()将IP字符串转化为网络字节序的整数值
inet_ntoa()[network to ascill]
- inet_ntoa()将in_addr结构体输出成IP字符串 print(mysocket.sin_addr);
struct timeval
#include "sys/time.h"
struct timeval
{
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
Select
- int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);
- select(A,B,C,D,E) A需要检查的文件描述字个数+1,B检查可读性的一组文件描述符,C检查可写性的一组文件描述符,D异常文件描述符,E多久返回超时